赞
踩
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
1.单向、双向
2.带头、不带头
3.循环、非循环
无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如
哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。
class Node { public int data; public Node next;//存储对象引用 public Node(int data) { this.data = data; //这里没有初始化next的引用是,不知道next当前指向那个 //节点 } } public class MySingleList { public Node head;//作用是,定位头节点的引用 //下面就可以定义方法了 }
class Node { public int data; public Node next;//存储对象引用 public Node(int data) { this.data = data; //这里没有初始化next的引用是,不知道next当前指向那个 //节点 } } public class MySingleList { public Node head;//作用是,定位头节点的引用 //头插法 public void addFirst(int data) { //1、通过data构造一个Node对象 Node node = new Node(data); //2、 if(this.head == null) { //第一次插入 this.head = node; }else { node.next = this.head; this.head = node; } } //尾插法 public void addLast(int data){ Node node = new Node(data); if(this.head == null) { this.head = node; return; } Node cur = this.head; while (cur.next != null) { cur = cur.next; } cur.next = node; } /** * 找到index-1位置的节点 * @param index * @return */ public Node searchPrev(int index) { int count = 0; Node cur = this.head; while (count < index-1) { cur = cur.next; count++; } return cur; } //任意位置插入,第一个数据节点为0号下标 public void addIndex(int index,int data) { Node node = new Node(data); if(index < 0 || index > size()) { System.out.println("index不合法"); return; } if(index == 0) { addFirst(data); return; } Node cur = searchPrev(index); node.next = cur.next; cur.next = node; } //得到单链表的长度 public int size() { Node cur = this.head; int count = 0; while (cur != null) { count++; cur = cur.next; } return count; } //查找是否包含关键字key是否在单链表当中 public boolean contains(int key) { Node cur = this.head; while (cur != null) { if(cur.data == key) { return true; } cur = cur.next; } return false; } /** * 找到关键字Key的前驱 * @param key * @return */ public Node searchPrevNode(int key) { Node cur = this.head; while (cur.next != null) { if(cur.next.data == key) { return cur; } cur = cur.next; } //退出循环,cur已经走到了链表的尾部 return null;//没有key的前驱 } //删除第一次出现关键字为key的节点 public void remove(int key){ //1、头节点 if(this.head.data == key) { this.head = this.head.next; return; } //2、找需要删除节点的前驱 Node prev = searchPrevNode(key); if(prev == null) { return; } Node del = prev.next;//就是要删除的节点的引用 prev.next = del.next; } //删除所有值为key的节点 public void removeAllKey(int key) { Node prev = this.head; Node cur = this.head.next; while (cur != null) { if(cur.data == key) { prev.next = cur.next; }else { prev = cur; } cur = cur.next; } if(this.head.data == key) { this.head = this.head.next; } } public void display() { Node cur = this.head; while (cur != null) { System.out.print(cur.data+" "); cur = cur.next; } System.out.println(); } /** * 从指定的节点开始打印 * newHead * @param newHead */ public void display2(Node newHead) { Node cur = newHead; while (cur != null) { System.out.print(cur.data+" "); cur = cur.next; } System.out.println(); } public void clear() { this.head = null; } public Node reverseList() { Node cur = this.head; Node newHead = null; Node prev = null; while (cur != null) { Node curNext = cur.next; if(curNext == null) { newHead = cur; } cur.next = prev; prev = cur; cur = curNext; } return newHead; } public Node middleNode() { Node fast = this.head; Node slow = this.head; while (fast != null && fast.next != null) { //while (fast.next != null && fast != null) { fast = fast.next.next; slow = slow.next; } return slow; } public Node findKthToTail(int k) { if(k <= 0) { return null; } Node fast = this.head; Node slow = this.head; while (k-1 > 0) { if(fast.next !=null) { fast = fast.next; k--; }else { System.out.println("没有这个节点"); return null; } } while (fast.next != null) { fast = fast.next; slow = slow.next; } return slow; } public Node partition(int x) { // write code here Node bs = null; Node be = null; Node as = null; Node ae = null; Node cur = this.head; while (cur != null) { if(cur.data < x) { if(bs == null) { bs = cur; be = cur; }else { be.next = cur; be = be.next; } }else { if(as == null) { as = cur; ae = cur; }else { ae.next = cur; ae = ae.next; } } cur = cur.next; } /* 把新的链表串起来 1、两个段内 可能有一个是空的 如果as不等于空,ae.next = null; 2、如果两个段都有数据 be.next = as; */ /*if(bs == null) { return as; } //bs != null; be.next = as; if(as != null) { ae.next = null; } return bs;*/ if(bs == null || as == null) { return this.head; }else { ae.next = null; be.next = as; } return bs; } public Node deleteDuplication() { Node cur = this.head; Node newHead = new Node(-1); Node tmp = newHead; while (cur != null) { if(cur.next != null && cur.data == cur.next.data) { while (cur.next != null && cur.data == cur.next.data) { cur = cur.next; } cur = cur.next; }else { tmp.next = cur; tmp = tmp.next; cur = cur.next; } } tmp.next = null; return newHead.next; } public boolean chkPalindrome() { if(this.head == null) { return false; } //只有1个节点的时候,也是回文 if(this.head.next == null) { return true; } //1、找到中间位置 Node fast = this.head; Node slow = this.head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; } //slow就是中间位置。开始进行第2步 //2、进行反转 Node cur = slow.next; while (cur != null ) { Node curNext = cur.next; cur.next = slow; slow = cur; cur = curNext; } //3、开始判断 while (this.head != slow) { if(this.head.data != slow.data) { return false; } if(this.head.next == slow) { //偶数情况下 return true; } this.head = this.head.next; slow = slow.next; } return true; } public boolean hasCycle() { Node fast = this.head; Node slow = this.head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if(fast == slow) { break; } } if(fast == null || fast.next == null) { return false; } return true; } public Node detectCycle() { Node fast = this.head; Node slow = this.head; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if(fast == slow) { break; } } if(fast == null || fast.next == null) { return null; } slow = this.head; while (slow != fast) { fast = fast.next; slow = slow.next; } return slow; } }
public class TestDemo {
public static void main(String[] args) {
MySingleList mySingleList = new MySingleList();
mySingleList.addLast(1);
mySingleList.addLast(12);
mySingleList.addLast(31);
mySingleList.addLast(41);
//等等
}
这里只要是一些基础的方法,一定要掌握反转,回文等,要掌握多指针的思想方法和定义一个哨兵节点的方法,注意方法的时间复杂度和空间复杂度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。