双向链表其实是单链表的改进。
当我们对单链表进行操作时,有时你要对某个结点前面的一个结点进行操作时,又必须从表头开始查找。这是由单链表结点的结构所限制的。因为单链表每个结点只有一个存储直接子结点地址的链域,那么能不能定义一个既有存储直接子结点地址的链域,又有存储直接父结点地址的链域的这样一个双链域结点结构呢?这就是双向链表。
在双向链表中,结点除含有数据域外,还有两个链域,一个存储直接子结点地址,一般称之为右链域;一个存储直接父结点地址,一般称之为左链域。
双向链表节点类
package com.dy.lkd17;
public class LinkNode {
private Object obj; //节点里面的数据对象
private LinkNode parent; //父节点
private LinkNode child; //子节点
//在创建节点对象时候就传入节点中的数据对象
public LinkNode(Object obj){
this.obj = obj;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public LinkNode getParent() {
return parent;
}
public void setParent(LinkNode parent) {
this.parent = parent;
}
public LinkNode getChild() {
return child;
}
public void setChild(LinkNode child) {
this.child = child;
}
}
对链表的使用和集合框架类似,最基本的使用就是能够实现数据的查找、插入、删除、合并、排序、统计以及简单计算等的操作。
package com.dy.lkd17;
public class LinkList {
public static LinkNode front = null; // 第一个节点
public static LinkNode last = null; // 最后一个节点
public static void main(String[] args) {
// 加入节点
LinkList list = new LinkList();
list.add("aa");
list.add("bb");
list.add("cc");
// 插入节点
list.insertIndexOf(1, "ddd");
//更新节点
list.UpdateLinkNode(0,"aa->abc");
// 删除节点
list.deleteLinkNode(3);
// 遍历链表
list.printLinkList(front);
}
/*
* 插入节点
*/
public void add(Object obj) {
// 创建一个新的节点
LinkNode node = new LinkNode(obj);
if (null == front) { // 如果链表为空
front = node; // 新建节点为第一个节点
last = front;
} else {
last.setChild(node); // 最后一个节点变为子节点
node.setParent(last);
last = node; // 改变最后节点的指向
}
}
/*
* 在指定位置插入节点
*/
private void insertIndexOf(int index, Object obj) {
if (this.getLength() < index || index < 0) {
throw new java.lang.RuntimeException("下标越界:" + index + ",size:"
+ this.getLength());
} else {
// 创建一个新的节点
LinkNode newNode = new LinkNode(obj);
// 得到当前索引位置的节点
LinkNode node = this.getLinkNode(index);
if (index == 0) { // 如果链表没有节点
front = newNode;
} else {
// 得到父节点
LinkNode fNode = node.getParent();
// 设置新的引用关系
fNode.setChild(newNode);
newNode.setParent(fNode);
}
// 设置新的引用关系
newNode.setChild(node);
node.setParent(newNode);
}
}
/*
* 指定索引删除节点
*/
public void deleteLinkNode(int index) {
if (this.getLength() < index || index < 0) {
throw new java.lang.RuntimeException("下标越界:" + index + ",size:"
+ this.getLength());
} else {
// 得到当前索引位置的节点
LinkNode node = this.getLinkNode(index);
// 得到父节点
LinkNode fNode = node.getParent();
// 得到子节点
LinkNode cNode = node.getChild();
if (fNode == null) { // 第一个节点
front = cNode;
} else if (cNode == null) { // 最后一个节点
fNode.setChild(null);
} else {
fNode.setChild(cNode);
cNode.setParent(fNode);
}
}
}
/**
* 修改对象节点
*/
public void UpdateLinkNode(int index, Object obj) {
if (this.getLength() < index || index < 0) {
throw new java.lang.RuntimeException("下标越界:" + index + ",size:"
+ this.getLength());
} else {
// 得到当前索引位置的节点
LinkNode node = this.getLinkNode(index);
node.setObj(obj);
}
}
/*
* 链表长度
*/
public int getLength() {
int count = 0;
if (front == null) {
return count;
}
LinkNode node = front.getChild();
while (null != node) {
count++;
node = node.getChild();
}
return count + 1;
}
/*
* 得到所在位置的节点
*/
public LinkNode getLinkNode(int index) {
if (this.getLength() < index || index < 0) {
throw new java.lang.RuntimeException("下标越界:" + index + ",size:"
+ this.getLength());
} else {
int num = 0;
LinkNode node = front;
while (num != index) {
node = node.getChild();
num++;
}
return node;
}
}
/*
* 遍历链表
*/
public void printLinkList(LinkNode root) {
if (null != root) {
Object data = root.getObj();
System.out.println(data);
LinkNode temp = root.getChild();
printLinkList(temp);
}
}
}