1、链表
链表是一种数据结构,是线性表。包括双向单链表、双向链表、循环链表等等。链表的具体结构这里就不说了,这里主要探讨的是如何用Java语言中实现双链表,因为Java没有C和C++那样的指针。
2、双向链表的实现
2.1、链表类
LinkList.java
package sxd.learn.algorithms;
/**
* @author Xiaodong
* date 2014年10月26日
* desc List
* 双向链表的实现
*/
public class LinkList<T> {
public LinkList(){
iSize = 0;
head = new Node<T>();
tail = new Node<T>();
head.next = tail;
tail.prev = head;
}
public void add(T item){
Node<T> node = new Node<T>(item, null, null);
tail.prev.next = node;
node.prev = tail.prev;
tail.prev = node;
node.next = tail;
iSize++;
}
public boolean isEmpty(){
return iSize == 0;
}
public T get(int index ){
if(index > iSize -1 || index <0 ){
throw new IndexOutOfBoundsException();
}
Node<T> current = new Node<T>(null,head,null);
current = current.prev.next;
for (int i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
public int getSize(){
return iSize;
}
/**
*
* 返回索引(从0开始)
*/
public int search(T data){
Node<T> current = new Node<T>(null,head,null);
current = current.prev.next;
for (int i = 0; i < iSize; i++) {
if (current.data == data) {
return i;
}
current = current.next;
}
return -1; // -1表示没有搜索到
}
//无法插入元素
public void insert(T data, T item){
if(search(data) == -1)
{
System.out.println("没有找到插入点");
System.exit(0);
}
Node<T> current = new Node<T>(null,head,null);
current = current.prev.next;
for (int i = 0; i < iSize; i++) {
if (current.data == data){
break;
}
current = current.next;
}
Node<T> iNode = new Node<T>(item,null,null);
iNode.prev = current;
iNode.next = current.next;
current.next.prev = iNode;
current.next = iNode;
iSize++;
}
public void delete(T item){
if(search(item) == -1)
{
System.out.println("链表中没有该节点");
System.exit(0);
}
Node<T> current = new Node<T>(null,head,null);
current = current.prev.next;
for (int i = 0; i < iSize; i++) {
if (current.data == item){
break;
}
current = current.next;
}
current.next.prev = current.prev;
current.prev.next = current.next;
iSize--;
}
public void print(){
Node<T> current = new Node<T>(null,head,null);
current = current.prev.next;
for (int i = 0; i < iSize; i++) {
System.out.print( current.data + " ");
current = current.next;
}
}
private int iSize;
private Node<T> head;
private Node<T> tail;
/**
* 节点类
*/
private class Node<AnyType> {
public Node(){
this.data = null;
this.prev = null;
this.next = null;
}
public Node(AnyType data, Node<AnyType> prev, Node<AnyType> next){
this.data = data;
this.prev = prev;
this.next = next;
}
AnyType data;
Node<AnyType> prev;
Node<AnyType> next;
}
}
上面的代码有个瑕疵就是在插入节点的时候,无法在头结点后的第一个位置插入结点,因为我这里的插入操作是以结点中的数据为依据,因为头结点无数据,所以无法在其后插结点,读者可修改插入操作为以结点的索引为插入依据,这样就能在头结点后插入结点了。
这里设置一个tail尾节点是为了方便add操作。
2.2、测试类
TestLinkList.java
package sxd.learn.algorithms;
public class TestLinkList {
public static void main(String[] args) {
LinkList iList = new LinkList<Integer>();
iList.add(9);
iList.add(16);
iList.add(4);
iList.add(1);
iList.print();
System.out.println("\n<---------->");
iList.insert(4, 25);
iList.print();
System.out.println("\n<---------->");
iList.delete(16);
iList.print();
System.out.println("\n<---------->");
System.out.println("search:" + iList.search(4));
System.out.println("size:" + iList.getSize());
System.out.println("\n<---------->");
}
}