赞
踩
链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。
链表在物理上不连续 在逻辑上连续
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
1. 单向或者双向
2. 带头或者不带头
3. 循环或者非循环
在这么多链表结构中我们主要学习两种
public class SingleLinkedList { //头插法 public void addFirst(int data){ } //尾插法 public void addLast(int data){ } //任意位置插入,第一个数据节点为0号下标 public void addIndex(int index,int data){ } //查找是否包含关键字key是否在单链表当中 public boolean contains(int key){ return false; } //删除第一次出现关键字为key的节点 public void remove(int key){ } //删除所有值为key的节点 public void removeAllKey(int key){ } //得到单链表的长度 public int size(){ return -1; } public void clear() { } public void display() {} }
实现上面的接口即可
public class SingleLinkedList { //内部类 实现了一个节点 static class ListNode { public int val; //节点的值 public ListNode next; //节点中储存了下一个节点的地址 public ListNode(int val) { this.val = val; } //初始化节点的构造方法 } //永远指向头节点 public ListNode head; //打印链表中所有节点的值 public void show() { ListNode cur = head; //记录头节点的位置 遍历不改变头节点位置 while (cur != null) { System.out.print(cur.val + " "); cur = cur.next; //当cur不为空时 打印每个节点的val值 使cur指向下一个节点 } System.out.println(); } //头插法 public void addFirst(int data) { ListNode node = new ListNode(data); //新建一个节点 将这个节点头插 node.next = head; //将新节点指向头节点 成为新的头节点 head = node; //head永远指向头节点 head也改为node } //尾插法 public void addLast(int data) { ListNode node = new ListNode(data); //新建一个节点 将这个节点尾插 if (head == null) { head = node; //如果此时链表为空 那么该节点就是新的头节点 return; } ListNode cur = head; //记录头节点 while (cur.next != null) { cur = cur.next; } //此时cur指向的就是最后一个节点 //只需要把最后一个节点指向node cur.next = node; } //任意位置插入,第一个数据节点为0号下标 public void addIndex(int index, int data) { int len = size(); //判断下标的合法性 if (index < 0 || index > len) { throw new IndexOutOfBoundsExcption("在任意位置插入数据时,index位置不合法: " + index); } //如果插入位置时头位置 则是头插 if (index == 0) { addFirst(data); } //如果插入位置时尾部 则是尾插 if (index == len) { addLast(data); } } //查找是否包含关键字key是否在单链表当中 public boolean contains(int key) { ListNode cur = head; while (cur != null) { if (cur.val == key) { return true; } cur = cur.next; } return false; } //删除第一次出现关键字为key的节点 public void remove(int key) { if (head == null) { return; } //如果头节点是要移除的节点 if (head.val == key) { head = head.next; return; } ListNode prev; } //查找目标节点的上一个节点 private ListNode searchPrev(int key) { ListNode prev = head; while (prev.next != null) { if (prev.next.val == key) { return prev; } else { prev = prev.next; } } return null; } //删除所有值为key的节点 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 int size() { int count = 0; ListNode cur = head; //如果是引用类型用equals比较 while (cur != null) { count++; cur = cur.next; } return count; } public void clear() { //this.head = null; while (head != null) { ListNode headNext = head.next; head.next = null; head = headNext; } } public void display() { ListNode cur = head; while (cur != null) { System.out.println(cur.val); cur = cur.next; } } }
LinkedList的底层是双向链表结构,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
public class MyLinkedList { static class ListNode { public int val; public ListNode prev; //储存上一个节点的位置 public ListNode next; //储存下一个节点的位置 public ListNode(int val) { this.val = val; } } //获取双向链表的长度 和双向无关 public ListNode head; public ListNode last; //获取链表的长度 public int size() { int len = 0; ListNode cur = head; //遍历链表求长度 while (cur != null) { len++; cur = cur.next; } return len; } //打印链表内容 public void display() { ListNode cur = head; while (cur != null) { System.out.print(cur.val); cur = cur.next; } System.out.println(); } //查找某个关键字key是否在链表中 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); //如果链表为空 插入的同时初始化头节点和尾节点 if (head == null) { head = node; last = node; return; } node.next = head; head.prev = node; head = node; } //尾插法 public void addLast(int data) { ListNode node = new ListNode(data); if (head == null) { head = node; last = node; return; } node.prev = last; last.next = node; last = node; } public void addIndex(int index, int data) { int size = size(); if (index < 0 || index > size) { throw new IndexOutOfBounds("双向链表index下标不合法:" + index); } if (index == 0) { addFirst(data); return; } if (index == size) { addLast(data); return; } ListNode cur = head; while (index != 0) { cur = cur.next; index--; } ListNode node = new ListNode(data); node.next = cur; cur.prev.next = node; node.prev = cur.prev; cur.prev = node; } public void remove(int key) { ListNode cur = head; while (cur != null) { if (cur.val == key) { //开始删除 if (cur == head) { //如果是头节点 删除头节点 head = head.next; //如果删除后还有节点 if (head != null) { head.prev = null; } else { last = null; //此时head = head.next head已经为null //只需要将last也置为null即可 } } else { cur.prev.next = cur.next; //将cur之前的节点next指向改为cur的下一个节点 //判断cur是否为尾节点 if (cur.next != null) { cur.next.prev = cur.prev; //将后面节点的prev指向cur的prev } else { last = cur.prev; //如果为最后一个节点 就把last向前移 } } return; } else { cur = cur.next; } } } public void removeAllKey(int key){ ListNode cur = head; //逻辑和删除一个元素一模一样 while (cur != null) { if (cur.val == key) { //开始删除 if (cur == head) { //如果是头节点 删除头节点 head = head.next; //如果删除后还有节点 if (head != null) { head.prev = null; } else { last = null; //此时head = head.next head已经为null //只需要将last也置为null即可 } } else { cur.prev.next = cur.next; //将cur之前的节点next指向改为cur的下一个节点 //判断cur是否为尾节点 if (cur.next != null) { cur.next.prev = cur.prev; //将后面节点的prev指向cur的prev } else { last = cur.prev; //如果为最后一个节点 就把last向前移 } } } cur = cur.next; } } public void clear(){ ListNode cur = head; while (cur != null){ ListNode curNext = cur.next; cur.prev = null; cur.next = null; cur = curNext; } head = null; last = null; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。