链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。
value存数据,节点存下一个的地址,通过节点找下一个数据,每个节点都是一个对象
注意:
链式结构在逻辑上是连续的,但在物理上不一定连续】
现实中的节点一般都是从堆上申请出来的
从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续
链0pooooooooooooooooooo表有非常多种,以下情况组合起来就有八种链表结构
1.单向或双向
2.带头或不带头
3.循环或非循环
我们重点掌握两种
1.无头单向非循环列表:结构简单,一般不用来单独存数据,更多是作为其他数据结构的子结构,如哈希桶,图的邻接表等等
2.无头双向链表:在Java的框架中,LinkedList底层实现就是无头双向循环链表
- public class MySingleList {
- static class ListNode {
- public int val;//节点的值域
- public ListNode next;//下一个节点的地址
-
- public ListNode(int val) {
- this.val = val;
- }
-
- }
-
-
- public ListNode head;//表示当前链表的头节点
-
- public void createList() {
-
- ListNode node1 = new ListNode(12);
- ListNode node2 = new ListNode(23);
- ListNode node3 = new ListNode(34);
- ListNode node4 = new ListNode(45);
- ListNode node5 = new ListNode(56);
-
- node1.next = node2;
- node2.next = node3;
- node3.next = node4;
- node4.next = node5;
-
- this.head = node1;
-
- }
- }
- public void display() {
- ListNode cur = head;
- while (cur != null) {
- System.out.print(cur.val+" ");
- cur = cur.next;
- }
- System.out.println();
- }
注意head不能丢
- public int size(){
- int count = 0;
- ListNode cur = head;
- while (cur != null) {
- count++;
- cur = cur.next;
- }
- return count;
- }
- public boolean contains(int key){
- ListNode cur = head;
- while (cur != null) {
- if(cur.val == key) {
- return true;
- }
- cur = cur.next;
- }
- return false;
- }
- public void addFirst(int data){
- ListNode node = new ListNode(data);
- node.next = head;
- head = node;
- }
- public void addLast(int data){
- ListNode node = new ListNode(data);
- ListNode cur = head;
- if(cur == null) {
- head = node;
- return;
- }
- //找到链表的尾巴 注意是cur.next 不是cur
- while (cur.next != null) {
- cur = cur.next;
- }
- cur.next = node;
- }
- public void addIndex(int index,int data){
- if(index < 0 || index > size()) {
- System.out.println("index 不合法");
- return;
- }
- if(index == 0) {
- addFirst(data);
- return;
- }
- if(index == size()) {
- addLast(data);
- return;
- }
- ListNode cur = findIndexSubOne(index);
- ListNode node = new ListNode(data);
- node.next = cur.next;
- cur.next = node;
- }
-
- /**
- * 找到要删除节点位置的前一个节点
- * @param index
- * @return
- */
- private ListNode findIndexSubOne(int index) {
- ListNode cur = head;
- while (index-1 != 0) {
- cur = cur.next;
- index--;
- }
- return cur;
- }
- public void remove(int key){
- if(head == null) {
- return;
- }
- //单独删除头节点
- if(head.val == key) {
- head = head.next;
- return;
- }
- ListNode cur = searchPrev(key);
- if(cur == null) {
- System.out.println("没有你要删除的数字");
- return;
- }
- ListNode del = cur.next;
- cur.next = del.next;
- }
-
- /**
- * 找到关键字 key的前驱
- * @param key
- * @return
- */
- private ListNode searchPrev(int key) {
- ListNode cur = head;
- while (cur.next != null) {
- if(cur.next.val == key) {
- return cur;
- }
- cur = cur.next;
- }
- return null;
- }
- public void removeAllKey(int key){
- if(head == null) {
- return;
- }
- ListNode cur = head.next;
- ListNode prev = head;
- while (cur != null) {
- if(cur.val == key) {
- prev.next = cur.next;
- cur = cur.next;
- }else {
- prev = cur;
- cur = cur.next;
- }
- }
- if(head.val == key) {
- head = head.next;
- }
- }
- public void clear() {
- this.head = null;
- }