《java数据结构》--链表
来源:互联网 发布:c语言程序编程教学 编辑:程序博客网 时间:2024/05/20 20:02
java数据结构
参考:数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现
主要有以下几种类型
- 单向链表
- 双端链表
- 有序链表
- 双向链表
- 有迭代器的链表
链表的效率
这里顺便谈下链表和数组相比效率的优越性.在表头插入和删除的速度都很快,因为只需要改变一下引用所以花费O(1)的时间.平均起来查找,删除和在指定节点后插入数据都需要搜索一半的链结点.需要O(N)次比较和数组一样.然由于链表删除插入的时候不需要像数组那种元素的移动.所以效率还是要优于数组.还有一点就是链表的内存可以随时的扩展内存.而数组的内存是一开始就固定好的.这样就会导致数组的效率和可用性大大下降.链表劣势在于随机访问,无法像数组那样直接通过下标找到特定的数据项
java代码实现
单向链表
package cn.zlz.structure;/** * 单向链表 持有一个首部节点,可以实现栈,后进先出 */public class LinkedList<V> { // 链表头部 private Node first; // 长度 private int size; public LinkedList() { super(); } // 首部插入新的节点 public Node<V> insertFirst(V value) { Node<V> node = new Node<V>(value); // 新节点的next指向老节点 node.setNext(first); first = node; // 长度+1 size++; return node; } // 获取指定位置节点 public Node<V> get(int index) { if (this.isEmpty()) { throw new IndexOutOfBoundsException("链表为空"); } if (index >= size) { throw new IndexOutOfBoundsException("越界"); } Node node = first; while (index-- > 0) { node = node.getNext(); } return node; } // 删除指定位置节点 public Node<V> remove(int index) { if (this.isEmpty()) { throw new IndexOutOfBoundsException("链表为空"); } if (index >= size) { throw new IndexOutOfBoundsException("越界"); } // 待删除节点 Node<V> removeNode = null; // 待删除节点的上个节点 Node<V> pre = null; if (index == 0) { // 没有上个节点 pre = null; removeNode = first; first = removeNode.next; } else { pre = this.get(index - 1); // 已通过长度验证pre.next存在 removeNode = pre.next; pre.next = removeNode.next; } if (--size <= 0) { first = null; } return removeNode; } // 判断linkList是否为空 public boolean isEmpty() { return first == null; } // 获取链表长度 public int getSize() { return size; } @Override public String toString() { if (first == null) { return "LinkedList "; } return "LinkedList [" + first.toString() + "]"; } // 节点类 class Node<V> { private V value; private Node next; public Node() { super(); } public Node(V value) { super(); this.value = value; } public V getValue() { return value; } public void setValue(V value) { this.value = value; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } @Override public String toString() { return "Node [value=" + value + ", next=" + next + "]"; } } // 测试 public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<String>(); linkedList.insertFirst("a"); linkedList.insertFirst("b"); linkedList.insertFirst("c"); linkedList.insertFirst("d"); linkedList.insertFirst("e"); linkedList.insertFirst("f"); System.out.println(linkedList.toString()); LinkedList<String>.Node<String> node = linkedList.get(2); System.out.println(node.getValue()); LinkedList<String>.Node<String> removeNode = linkedList.remove(0); System.out.println(linkedList.toString()); System.out.println(node.getValue()); }}
双端单向链表
package cn.zlz.structure;/** * 双端单向链表 持有一个首部节点引用和尾部节点引用,可以实现队列,先进先出 * * 双端链表与传统链表非常相似.只是新增了一个属性-即对最后一个链结点的引用,单向链表只能从首部开始操作,双端链表首尾都可以 */public class DbPortLinkedList<V> { // 链表头部 private Node first; // 链表尾部 private Node last; // 长度 private int size; public DbPortLinkedList() { super(); } // 首部添加新的节点 public Node<V> insertFirst(V value) { Node<V> node = new Node<V>(value); // 新节点的next指向老节点 if (this.isEmpty()) { last = node; } node.setNext(first); first = node; // 长度+1 size++; return node; } // 尾部添加新的节点 public Node<V> insertLast(V value) { Node<V> node = new Node<V>(value); // 新节点的next指向老节点 if (this.isEmpty()) { first = node; last = node; return node; } last.setNext(node); last = node; // 长度+1 size++; return node; } // 获取指定位置节点 public Node<V> get(int index) { if (this.isEmpty()) { throw new IndexOutOfBoundsException("链表为空"); } if (index >= size) { throw new IndexOutOfBoundsException("越界"); } Node node = first; while (index-- > 0) { node = node.getNext(); } return node; } // 删除指定位置节点 public Node<V> remove(int index) { if (this.isEmpty()) { throw new IndexOutOfBoundsException("链表为空"); } if (index >= size) { throw new IndexOutOfBoundsException("越界"); } // 待删除节点 Node<V> removeNode = null; // 待删除节点的上个节点 Node<V> pre = null; if (index == 0) { // 没有上个节点 pre = null; removeNode = first; first = removeNode.next; } else { pre = this.get(index - 1); // 已通过长度验证pre.next存在 removeNode = pre.next; pre.next = removeNode.next; } // 长度-1,并验证链表是否为空 if (--size <= 0) { first = null; last = null; } return removeNode; } // 判断linkList是否为空 public boolean isEmpty() { return first == null && last == null; } // 获取链表长度 public int getSize() { return size; } @Override public String toString() { if (first == null) { return "DbPortLinkedList "; } return "DbPortLinkedList [" + first.toString() + "]"; } // 节点类 class Node<V> { private V value; private Node next; public Node() { super(); } public Node(V value) { super(); this.value = value; } public V getValue() { return value; } public void setValue(V value) { this.value = value; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } @Override public String toString() { return "Node [value=" + value + ", next=" + next + "]"; } } // 测试 public static void main(String[] args) { DbPortLinkedList<String> dbPortLinkedList = new DbPortLinkedList<String>(); dbPortLinkedList.insertFirst("a"); dbPortLinkedList.insertFirst("b"); dbPortLinkedList.insertLast("c"); dbPortLinkedList.insertFirst("d"); dbPortLinkedList.insertLast("e"); dbPortLinkedList.insertFirst("f"); System.out.println(dbPortLinkedList.toString()); DbPortLinkedList<String>.Node<String> node = dbPortLinkedList.get(2); System.out.println(node.getValue()); DbPortLinkedList<String>.Node<String> removeNode = dbPortLinkedList.remove(0); System.out.println(dbPortLinkedList.toString()); System.out.println(removeNode.getValue()); }}
有序链表
package cn.zlz.structure;/** * 有序单向链表:链表中的数据按从小到大排列 持有一个首部节点 * 有序链表插入数据效率为O(N),但查找跟删除最大数据就是表头数据效率为O(1).所以在最小数据存储频繁,但又不需要快速插入的时候有序链表是个不错的选择. */public class SortedLinkedList { // 链表头部 private Node first; // 长度 private int size; public SortedLinkedList() { super(); } // 首部插入新的节点 public Node insertFirst(Integer value) { Node node = new Node(value); // 查找位置,即找到前面一个节点和后面一个节点 Node pre = null;//插入位置前面节点 Node current = first;//插入位置后面节点 while (current != null && current.getValue()<value) { pre = current; current=current.next; } //最小的,插在第一个位置 if(pre == null){ first = node; }else{ pre.next = node; } //新插入的节点不管怎么next都指向当前节点 node.next = current; // 长度+1 size++; return node; } // 获取指定位置节点 public Node get(int index) { if (this.isEmpty()) { throw new IndexOutOfBoundsException("链表为空"); } if (index >= size) { throw new IndexOutOfBoundsException("越界"); } Node node = first; while (index-- > 0) { node = node.getNext(); } return node; } // 删除指定位置节点 public Node remove(int index) { if (this.isEmpty()) { throw new IndexOutOfBoundsException("链表为空"); } if (index >= size) { throw new IndexOutOfBoundsException("越界"); } // 待删除节点 Node removeNode = null; // 待删除节点的上个节点 Node pre = null; if (index == 0) { // 没有上个节点 pre = null; removeNode = first; first = removeNode.next; } else { pre = this.get(index - 1); // 已通过长度验证pre.next存在 removeNode = pre.next; pre.next = removeNode.next; } if (--size <= 0) { first = null; } return removeNode; } // 判断linkList是否为空 public boolean isEmpty() { return first == null; } // 获取链表长度 public int getSize() { return size; } @Override public String toString() { if (first == null) { return "SortedLinkedList "; } return "SortedLinkedList [" + first.toString() + "]"; } // 节点类 class Node { private int value; private Node next; public Node() { super(); } public Node(int value) { super(); this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } @Override public String toString() { return "Node [value=" + value + ", next=" + next + "]"; } } // 测试 public static void main(String[] args) { SortedLinkedList sortedLinkedList = new SortedLinkedList(); sortedLinkedList.insertFirst(4); sortedLinkedList.insertFirst(2); sortedLinkedList.insertFirst(3); sortedLinkedList.insertFirst(5); System.out.println(sortedLinkedList); }}
双向链表
package cn.zlz.structure;/** * 双向链表,注意画图来看 * 注意:双向链表需要初始化一个header头,但是这个header头不属于链表的一个元素 */public class DbLinkedList<V> { // 链表头部 private Node header; // 长度 private int size; public DbLinkedList() { super(); //创建表头 this.header = new Node(null, null, null); //表头自循环 this.header.next = this.header; this.header.pre = this.header; } // 首部添加新的节点 public Node<V> insert(int index,V value) { if (index > size) { throw new IndexOutOfBoundsException("越界"); } Node<V> current = null ; if(size == 0){ current = this.header; }else{ current = get(index); } Node<V> node = new Node<V>(value,current.pre,current); node.pre.next = node; node.next.pre = node; // 长度+1 size++; return node; } public Node<V> insertFirst(int index,V value) { return this.insert(0, value); } public Node<V> insertLast(int index,V value) { //面向对象 Node<V> node = new Node<V>(value,this.header.pre,this.header); node.pre.next = node; node.next.pre = node; // 长度+1 size++; return node; } // 首部添加新的节点 //注意:双向链表中的元素不包括header public Node<V> get(int index) { if (size==0 || index > size) { throw new IndexOutOfBoundsException("越界"); } Node<V> node = null; //如果是后半从后往前找 if(index>(size)/2){ System.out.println("从后往前找"); //header不属于链表,所以z最后一个是插入中的一个。 node = this.header.pre; int round = size-index; while (round-->=0) { node = node.pre; } }else{//从前往后找 System.out.println("从前往后找"); //header不属于链表,所以第一个是header的next,插入的时候对0单独处理了,执行get的时候至少已经插入一条 node = this.header.next; while (index-->0) { node = node.next; } } return node; } public Node<V> remove(int index){ if (size==0 || index > size-1) { throw new IndexOutOfBoundsException("越界"); } Node<V> toDelNode = this.get(index); toDelNode.pre.next = toDelNode.next; toDelNode.next.pre = toDelNode.pre; size--; return toDelNode; } // 获取链表长度 public int getSize() { return size; } // 判断linkList是否为空 public boolean isEmpty() { return size == 0; } public Node getHeader() { return header; } public void setHeader(Node header) { this.header = header; } public void setSize(int size) { this.size = size; } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); Node header = this.getHeader(); Node next = header.getNext(); stringBuilder.append(header.getPre().getValue()+":"+header.getValue()+":"+header.getNext().getValue()); while(next!=header){ stringBuilder.append(" "); stringBuilder.append(next.getPre().getValue()+":"+next.getValue()+":"+next.getNext().getValue()); next = next.next; } return stringBuilder.toString(); } // 节点类 class Node<V> { private V value;// 值 private Node pre;// 前一个节点 private Node next;// 后一个节点 public Node() { super(); } public Node(V value, Node pre, Node next) { super(); this.value = value; this.pre = pre; this.next = next; } public Node(V value) { super(); this.value = value; } public V getValue() { return value; } public void setValue(V value) { this.value = value; } public Node getPre() { return pre; } public void setPre(Node pre) { this.pre = pre; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; } @Override public String toString() { return "Node [value=" + value + ", pre=" + pre + ", next=" + next + "]"; } } // 测试 public static void main(String[] args) { DbLinkedList<String> dbLinkedList = new DbLinkedList<String>(); System.out.println(dbLinkedList.toString()); dbLinkedList.insert(0,"a"); System.out.println(dbLinkedList.toString()); dbLinkedList.insert(1,"b"); System.out.println(dbLinkedList.toString()); dbLinkedList.insert(2,"b"); System.out.println(dbLinkedList.toString()); dbLinkedList.insert(1,"c"); System.out.println(dbLinkedList.toString()); dbLinkedList.insert(4,"d"); System.out.println(dbLinkedList.toString()); dbLinkedList.insert(0,"e"); System.out.println(dbLinkedList.toString()); System.out.println(dbLinkedList.get(3).getValue());// dbLinkedList.insertFirst("f"); System.out.println(dbLinkedList.toString()); }}
0 0
- Java数据结构(一) ---链表
- java数据结构 链表
- 数据结构JAVA--链表
- 数据结构--链表(java)
- 【Java数据结构】链表
- Java数据结构----链表
- java--数据结构--链表
- Java 数据结构(链表)
- Java数据结构-链表
- 《java数据结构》--链表
- JAVA数据结构:链表
- java数据结构--链表
- java 数据结构-链表
- Java数据结构和算法--链表
- Java数据结构和算法--链表
- Java数据结构和算法--链表
- Java中的数据结构(2)----链表
- Java 数据结构和算法 链表
- xilinx zynq-7000 基本知识
- Object.keys方法之详解
- 使用BootStrap中的栅格系统后,页面调整变形的解决方法
- JQuery中常用选择器和方法的总结
- 修改ubuntu系统的时间
- 《java数据结构》--链表
- Android实现EditText文本颜色渐变
- 成员变量和局部变量的区别
- OC是动态语言体现在什么方面
- 打气球dfs
- android中如何设计触摸屏驱动touch screen driver
- [LeetCode]9. Palindrome Number
- LINUX操作系统VIM的安装和配置
- Android Launcher详解