链表及其基本操作的JAVA实现。

来源:互联网 发布:java多线程的两种方法 编辑:程序博客网 时间:2024/05/22 00:44

先来段代码:

package LinkList;import java.util.Hashtable;public class LinkList {Node head = null;public void addNote(int data) {Node newNode = new Node(data);if (head == null) {head = newNode;return;}Node intermediate = head;while (intermediate.next != null) {intermediate = intermediate.next;}intermediate.next = newNode;}public int length() {int length = 0;Node tmp = head;while (tmp != null) {length++;tmp = tmp.next;}return length;}/** * @param index:delete *            index node. *  *  */public boolean deleteindexnode(int index) {if (index < 1 || index > length()) {return false;}if (index == 1) {head = head.next;return true;}int i = 1;Node prenode = head;Node currnode = prenode.next;while (currnode != null) {if (i == index) {prenode.next = currnode.next;}i++;prenode = currnode;currnode = currnode.next;}return true;}public Node ordlist() {int temp = 0;Node cur = head;Node ne = cur.next;if (cur == null || ne == null) {return head;}while (cur.next != null) {while (ne != null) {if (cur.data > ne.data) {temp = cur.data;cur.data = ne.data;ne.data = temp;}ne = ne.next;}cur = cur.next;ne = cur.next;}return head;}public void printList() {Node temp = head;while (temp != null) {System.out.println(temp.data);temp = temp.next;}}public Node searchMidNode(){Node p =this.head;Node q=this.head;while (p!=null&&p.next!=null&&p.next.next!=null) {p = p.next.next;q = q.next;}return q;}public void deleteDuplecate() {Hashtable<Integer, Integer> hashtable = new Hashtable<Integer, Integer>();Node pre = head;Node cur = pre.next;while (cur != null) {if (hashtable.containsKey(cur.data)) {pre.next = cur.next;} else {hashtable.put(cur.data, 1);pre = cur;}cur = cur.next;}}/* * public void deleteDuplecatebyErgodic() { *  * Node cur = head; if (cur == null) { return; } // 外循环 while (cur != null) * { Node ne = cur; // 内循环 while (ne.next!= null) { if (cur.data == * ne.next.data) { ne.next = ne.next.next; } ne = ne.next; } // 内循环结束 cur = * cur.next; } // 外循环结束 *  * } */public void reverseList() {Node pReverseHead = head;Node pNode = head;Node pPrev = null;while (pNode != null) {Node pNext = pNode.next;if (pNext == null) {pReverseHead = pNode;}pNode.next = pPrev;pPrev = pNode;pNode = pNext;}this.head = pReverseHead;}public void printListReversely(Node head){if (head!=null) {printListReversely(head.next);System.out.println(head.data);}}public static void main(String[] args) {LinkList list = new LinkList();list.addNote(1);list.addNote(8);list.addNote(4);list.addNote(6);list.addNote(4);list.addNote(8);list.addNote(8);list.addNote(7);list.addNote(1);System.out.println("length:" + list.length());System.out.println("before:");list.printList();list.printListReversely(list.head);System.out.println("逆序输出");System.out.println("下面是中间结点:");System.out.println(list.searchMidNode().data);//list.printList();//list.ordlist();//System.out.println("Then");//list.printList();System.out.println("Reverse:");list.reverseList();list.printList();// System.out.println("Final");// list.deleteDuplecate();// list.printList();}}class Node {Node next;int data;public Node(int data) {this.data = data;}}
上面这段代码包含了链表的一些基本操作。

  如何在不知道头指针的情况下删除指定结点?分两种情况来讨论:

  1.如果待删除的结点是尾结点,那么无法删除。

  2.如果待删除的结点不是尾部节点,那么可以通过交换该结点与其后继结点的值,然后删除后继结点。

下面是具体的代码实现:

public Boolean deleteNode(Node node) {if (node.next == null) {return false;}int temp = node.data;node.data = node.next.data;node.next.data = temp;node.next = node.next.next;return true;}

如何判断2个链表结点相交?如果2个链表相交,则最后一个交点处肯定是尾结点(如果不是尾结点,那么肯定存在某个分叉的结点,而该结点会有2个指向,这显然是不可以的)。所以只要判断尾结点是否相同即可。下面是实现:

public Boolean isIntersect(Node p,Node q){if (p==null||q==null) {return false;}Node ptail=p;while (ptail.next!=null) {ptail=ptail.next;}Node qtail = q;while (qtail.next!=null) {qtail=qtail.next;}return qtail==ptail;//不需要使用data,因为都是尾结点,所以qtail.next和ptail.next都是null,实际比较的还是data。}
继续讨论,如果2个链表相交,那么如何寻找他们相交的第一个结点呢,接下来分析一下:如果给定2个相交的链表,那么这2个链表肯定有长有短,假定长链表的长度为a,短链表的长度为b,则长链表从a-b处与短链表同时遍历比较即可。这样即可找到第一个,甚至可以找到任意的一个他们共有的结点。下面是具体实现:

public Node searchFirstCommon(Node p, Node q) {// 首先判断是否相交,相交才能执行寻找第一个结点的操作。if (!this.isIntersect(p, q)) {return null;}int plenth = 0;int qlenth = 0;while (p != null) {// 找长度plenth++;p = p.next;}while (q != null) {// 找长度qlenth++;q = q.next;}// 将长链表“缩短”再遍历Node pNode = p;Node qNode = q;if (plenth > qlenth) {int t = plenth - qlenth;while (t != 0) {pNode = pNode.next;t--;}} else {int t = qlenth - plenth;while (t != 0) {qNode = qNode.next;t--;}}// 接下来同时遍历。while (pNode != qNode) {pNode = pNode.next;qNode = qNode.next;}return qNode;}


上述算法只需要分别遍历一次两个链表,时间复杂度为O(len1+len2),如果调用之前我们写过的统计长度和判断相交的方法,需要遍历2遍链表(每个方法遍历一遍,而我们这样写,在遍历一遍的同时做了两件事情:统计长度和得到尾结点,从而判断是否相交,不过这样做耦合性较差)。因此效率偏低。但是那样做会使得代码简洁,可用性强。

参考书:《JAVA程序员面试笔试宝典》   -----何昊、薛鹏、叶向阳 编著

0 0