欢迎讨论,转载请注明出处哦
前面一篇文章说明了线性表主要有三种结构:顺序表、单链表、双链表。
其实按照其实现的特点是两种实现方式:1、采用数组式的静态存储空间,即线性表;2、采用链
式的动态 存储空间,即是链表。
上一章实现了顺序表,这篇文章用于实现双链表。由于双链表具有的方法比顺序表多。
因此重新定义一个线性表接口:
package com.kiritor.linklist;
/**
* 线性表接口
* @author Kiritor
* */
public interface LinearTable<T>{
//判空
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<T> implements LinearTable<T> {
// 指向链表的头结点
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)