双向链表和我们前面讲的单链表最大的区别就是多了一个前驱结点
我们第一步还是定义Sequence接口,它里面都是双向链表一些基本的操作,增删查改等
Sequence接口定义如下:
public interface Sequence {
/**
* 向线性表中添加元素
* @param date 要存储的元素
*/
void add(Object date);
/**
* 线性表中删除元素
* @param index 要删除的元素下标
* @return 是否删除成功
*/
boolean remove(int index);
/**
* 在线性表中查找指定下标的元素
* @param index 要查找的索引
* @return
*/
Object get(int index);
/**
* 判断线性表中是否有指定元素
* @param data 要查找的元素内容
* @return
*/
boolean contains(Object data);
/**
* 修改线性表中指定索引的内容
* @param index 要修改元素下标
* @param newData 修改后的内容
* @return
*/
Object set(int index,Object newData);
/**
* 返回当前线性表的长度
* @return
*/
int size();
/**
* 清空线性表内容
*/
void clear();
/**
* 将线性表转为数组
* @return
*/
Object[] toArray();
下面是双向链表类中实现Sequence接口的方法实现:
首先我们先定义DoubleLinkListImpl类,
public class DoubleLinkedListImpl implements Sequence{
//表示头结点
private ListNode head;
//表示尾结点
private ListNode tail;
//链表长度
private int size;
//内部类ListNode
private class ListNode {
private ListNode prev;
private ListNode next;
Object data;
public ListNode(ListNode prev , Object data, ListNode next) {
this.prev = prev;
this.next = next;
this.data = data;
}
public ListNode(Object data) {
this.data = data;
}
}
}
该类中具体实现方法我们一步一步写出来:
checkIndex方法:
//检查索引index是否合法
private void checkIndex(int index) {
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Illeagle Index");
}
}
node方法:
//获取当前索引结点
private ListNode node(int index) {
ListNode tmp = head;
for(int i = 0;i<index;i++) {
tmp = tmp.next;
}
return tmp;
}
add方法:
/**
* 尾插法
*/
public void add(Object date) {
// TODO Auto-generated method stub
ListNode node = new ListNode(tail,date,null);
if(head == null) {
head = node;
}else {
tail.next = node;
}
tail = node;
size++;
}
remove方法:
public boolean remove(int index) {
// TODO Auto-generated method stub
checkIndex(index);
//要删除结点
ListNode now = node(index);
ListNode prevNode = now.prev;
ListNode nextNode = now.next;
//要删除的是头结点
if(prevNode == null) {
head = nextNode;
}else {
prevNode.next = now.next;
now.prev = null;
}
//要删除的是尾结点
if(nextNode == null) {
tail = now.prev;
}else {
nextNode.prev = now.prev;
now.prev = null;
}
size--;
return true;
}
get方法:
public Object get(int index) {
// TODO Auto-generated method stub
checkIndex(index);
return node(index).data;
}
contains方法:
public boolean contains(Object data) {
// TODO Auto-generated method stub
ListNode tmp = head;
while(tmp!=null) {
if(tmp.data.equals(data)) {
return true;
}
tmp = tmp.next;
}
return false;
}
set方法:
public Object set(int index, Object newData) {
// TODO Auto-generated method stub
checkIndex(index);
ListNode node = node(index);
node.data = newData;
return newData;
}
clear方法:
@Override
public void clear() {
// TODO Auto-generated method stub
for(ListNode tmp = head;tmp!=null;) {
ListNode next = tmp.next;
tmp.prev = tmp.next = null;
tmp.data = null;
tmp = next;
size--;
}
}
size方法:
public int size() {
// TODO Auto-generated method stub
return size;
}
toArray方法:
public Object[] toArray() {
// TODO Auto-generated method stub
Object[] object = new Object[size];
int i = 0;
for(ListNode tmp = head;tmp!=null;tmp = tmp.next) {
object[i++] = tmp.data;
}
return object;
}
完整代码链接:https://github.com/dukaichao/DataStructure/tree/master/dkc_ds_0319