欢迎讨论,转载请注明出处哦
前面一篇文章说明了线性表主要有三种结构:顺序表、单链表、双链表。
其实按照其实现的特点是两种实现方式:1、采用数组式的静态存储空间,即线性表;2、采用链
式的动态 存储空间,即是链表。
上一章实现了顺序表,这篇文章用于实现双链表。由于双链表具有的方法比顺序表多。
因此重新定义一个线性表接口: package com.kiritor.linklist; /** * 线性表接口 * @author Kiritor * */ public interface LinearTable{ //判空 public boolean isEmpty(); //获取长度 public int getLength(); //返回某个位置的元素 public T getData(int index); //设置index位置的元素,并返回先前的元素 public T setData(int index,T element); //插入一个元素,位置没有限定(插入链表尾部) public boolean addData(T element); //在指定的位置插入一个元素 public boolean addData(int index,T element); //删除某个位置的元素,并返回该元素 public T removeData(int index); //清空线性表 public boolean clearData(); //删除尾部 public boolean removeTail(); } 接下来就是实现了
package com.kiritor.linklist; /** * java版双向链表的实现 * * @author Kiritor */ public class DBLinkList implements LinearTable { // 指向链表的头结点 private Node head; // 指向链表的尾结点 private Node tail; private int size = 0;// 链表的元素个数 public DBLinkList() { this.head = new Node(); this.tail = null; } public DBLinkList(T data) { this.head = new Node(null, data, null); this.tail = this.head; this.size++; } @Override public boolean isEmpty() { // TODO Auto-generated method stub return this.size == 0; } // 获得链表的长度 public int getLength() { return this.size; } // 获取指定位置结点,下表从0开始 public Node getNode(int index) { if (index < 0 || index > this.size - 1) throw new IndexOutOfBoundsException("访问位置非法越界!"); // 根据index所出的位置决定是从前遍历还是从后遍历 if (index <= this.size / 2) {// 位置在前半部分,则从头开始搜索 Node curent = this.head; for (int i = 0; i <= this.size / 2 && curent != null; i++, curent = curent.next) if (i == index) return curent; } else {// 位置在后半部分,则从后开始往前搜索 Node curent = this.tail; for (int i = this.size - 1; i > this.size / 2 && curent != null; i--, curent = curent.pre) if (i == index) return curent; } return null; } // 获取指定位置的结点元素 public T getData(int index) { return this.getNode(index).data; } @Override public T setData(int index, T element) { return null; } // 在链表的头部插入元素,不指定位置默认在头部插入 @Override public boolean addData(T element) { // 前驱引用为null,后继引用为头结点 Node node = new Node(null, element, this.head); this.head.pre = node;// 改变前驱引用 // 修改链表的头结点 this.head = node; if (tail == null) tail = this.head; this.size++; // System.out.println(head.data+""+this.size); return true; } // 尾部插入 public boolean addTail(T data) { if (this.head == null) { this.head = new Node(null, data, null); this.tail = this.head; } else { Node newnode = new Node(this.tail, data, null); this.tail.next = newnode; this.tail = newnode; } this.size++; // System.out.println(tail.data+""+this.size); return true; } //下表从0开始 @Override public boolean addData(int index, T element) { if (index < 0 || index > this.size) throw new IndexOutOfBoundsException("不能在该位置插入元素,索引越界"); if (this.head == null) this.addTail(element);// 尾部插入 else { if (index == 0) this.addData(element);// 头部插入 else { Node prev = this.getNode(index - 1);// 找到index-1处的节点 Node next = prev.next; Node newnode = new Node(prev, element, next);// 分配节点 prev.next = newnode; next.pre = newnode; this.size++; } } return true; } public String toString() { if (this.isEmpty()) return "[]"; else { StringBuffer st = new StringBuffer("["); for (Node curent = this.head; curent != null; curent = curent.next) st.append(curent.data.toString() + " ,"); st.append("]"); return st.toString(); } } // 反向遍历链表 public String reversetoString() { if (this.isEmpty()) return "[]"; else { StringBuffer st = new StringBuffer("["); for (Node curent = this.tail; curent != null; curent = curent.pre) st.append(curent.data.toString() + " ,"); st.append("]"); return st.toString(); } } /**删除指定位置的结点,下表从0开始*/ @Override public T removeData(int index) { if (index < 0 || index > this.size - 1) throw new IndexOutOfBoundsException("不能删除该位置的元素,索引越界"); Node del = null; if (index == 0) {// 删除的为头节点 del = this.head; this.head = this.head.next; this.head.pre = null; size--; } else if(index==size-1) { Node prev = this.getNode(index - 1);//找到删除位置的前驱 del = prev.next;//找到要删除的结点 prev.next = del.next; if (del.next != null) del.next.pre = prev; del.pre = null; del.next = null; size--; this.tail.next = null; this.tail.pre=prev; this.tail = prev; } else { Node prev = this.getNode(index - 1);//找到删除位置的前驱 del = prev.next;//找到要删除的结点 prev.next = del.next; if (del.next != null) del.next.pre = prev; del.pre = null; del.next = null; size--; } return null; } @Override public boolean removeTail() { removeData(this.size-1 ); return false; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } @Override public boolean clearData() { this.head = null; this.tail = null; this.size = 0; return true; } /** 链表的节点类型 */ class Node { public T data; public Node pre;// 便于访问的需要,设置为public public Node next; public Node() { }; public Node(Node pre, T data, Node next) { this.data = data; this.pre = pre; this.next = next; } } } 简单的看看输出结果:
对于其具体分析就一个removeData(int index)方法为例吧(index>=1&&index<=size-1)