线性链表——双向链表

双向链表定义:

双向链表(double linked list): 是在单表单的每个结点中,再设置一个指向前驱结点的指针域。因此,在双向链表中的结点都有两个指针域,一个指向前驱,一个指向后继。

双向链表的存储结构

typedef struts DulNode{

Element data;

Struct DulNode *prior;前驱指针

Struct DulNode *next;后继指针

}DulDouble, *DulLinkList;

双向链表的插入与删除

双向链表的插入:

假设结点为s,要将结点插入到结点p和p->next中,我们需要下面几步:

s.prev = p;

s.next = p.next;

p.next.prev = s;

p.next = s;

总结起来就是:先搞定s的前驱后继,再搞定后结点的前驱,最后解决前驱结点的后继

双向链表的删除:

要删除p结点,只需要两个步骤:

p.next.prev = p.prev;

p.prev.next = p.next;

free(p);

总结:

相对于单链表,双向链表多了一个指针域,空间上要占用略多一点,但它有很好的对称性,使得对某个结点的前后结点操作更容易,可以提高算法的时间性能,这是牺牲空间换取的。

Java程序实现双链表:

package com.aclie.dataStructe4.sqeList;

public class MyDoubleLinkList {
private int length =0;//当前长度
private Node head;//头结点
private Node tail;//当前结点结点 public MyDoubleLinkList(){
initLink();
}
public void initLink(){
head = new Node(null);
tail = new Node(null);
this.head = tail;
length++;
} //获取链表长度
public int getSize(){
return length;
}
//判断链表是否为空
public boolean getEmpty(){
return getSize()==0;
}
//根据索引查找元素 从第一个有效值开始
public Node getNode(int index){
Node p;
if(index < 0 || index > length ){
System.out.println("参数错误");
}
if(index < this.length/2){
p = this.head;
for(int i=0; i<index; i++){
p = p.next;
}
}else{
p = this.tail;
for(int i= length; i>index;i--){
p = p.prev;
}
}
return p;
} public Object getData(int index){
return getNode(index).data;
} //在头结点处插入
public boolean addHead(Object e){
//前驱引用为null,后继为node
Node node = new Node(e, null, this.head);
//改变头结点的前驱后继
this.head.prev = node;
this.head = node;
if(tail == null){
tail = this.head;
}
length++;
return true;
}
//在尾结点插入
public boolean addTail(Object e){
if(this.head == null){
this.head = new Node(e,null,null);
this.tail = this.head;
}else{
Node node = new Node(e,this.tail,null);
this.tail.next = node;
this.tail = node; }
length++;
return true; }
//在指定位置插入元素
public boolean addData(int index,Object ele){
if(index <0 || index > this.length){
System.out.println("参数错误");
}
if(this.head == null){
this.addTail(ele);//用尾插法
}else{
if(index == 0){
addHead(ele);//用头插法
}else{
Node p = this.getNode(index);//要插入处的结点
Node n = p.next;
Node node = new Node(ele,p,n);//要插入的结点
n.prev = node;
p.next = node;
length ++; }
} return true;
} public void removeData(int index){
if(index < 0 || index > length){
System.out.println("参数错误");
}else{
Node del = null;
if(index == 0){
del = this.head;
this.head = this.head.next;
this.head.prev = null;
length--;
}else if(index == (length-1)){
Node p = this.getNode(index-1);//得到要删除结点的前驱结点
del = p.next;//要删除的结点
p.next = del.next;
if(del.next != null){
del.next.prev = p;
}
del.next = null;
del.prev = null;
length --; this.tail.next = null;
this.tail.prev = p;
this.tail = p;
}
else{
Node p = this.getNode(index-1);//要删除结点的前驱结点
del = p.next;//要删除的结点
p.next = del.next;
if(del.next != null){
del.next.prev = p;
}
del.prev = null;
del.next = null;
length--;
} }
}
//打印所有链表中的元素
public void print(){
Node current = this.head;
while(current != null){
System.out.println(current.data);
current = current.next;
}
}
//反向打印链表
public void reversePrint(){
Node current = this.tail;
while(current != null){
System.out.println(current.data);
current = current.prev;
}
}
public static void main(String args[]){
MyDoubleLinkList linkList = new MyDoubleLinkList();
linkList.addHead("aaaa");
// System.out.println(linkList.getData(1));
linkList.addTail("bbbb");
// System.out.println(linkList.getData(3));
linkList.addData(2, "eeee");
// linkList.print();
linkList.removeData(2);
linkList.print();
System.out.println(".....");
linkList.reversePrint();
} }
class Node{
Node prev;//指针域中前驱
Node next;//指针域中后继
Object data;//数据域
public Node(Node current){
prev = current;
next = current;
}
//双链表前驱后继及数字域
public Node(Object d, Node p,Node n){
this.data = d;
this.prev = p;
this.next = n;
}
public Node getPrev() {
return prev;
}
public void setPrev(Node prev) {
this.prev = prev;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
} }

大话数据结构(八)Java程序——双向链表的实现的更多相关文章

  1. Java程序员从笨鸟到菜鸟全部博客目录

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 大学上了一年半,接触java也一年半了,虽然中间也有其他东西的学习,但是还是以java为主 ...

  2. Java程序员进击书籍推荐

    计算机基础 计算机科学导论 计算机操作系统 操作系统原理及应用(Linux) Java 基础和进阶 疯狂Java讲义 Java 核心基础卷1/2 Java编程思想 Java 8实战 jls11 Eff ...

  3. 《Java程序员由笨鸟到菜鸟》

    <Java程序员由笨鸟到菜鸟> 在众多朋友的支持和鼓励下,<Java程序员由菜鸟到笨鸟>电子版终于和大家见面了.本电子书涵盖了从java基础到javaweb开放框架的大部分内容 ...

  4. 【Java】 大话数据结构(5) 线性表之双向链表

    本文根据<大话数据结构>一书,实现了Java版的双向链表. 在每个数据结点中都有两个指针,分别指向直接后继和直接前驱,这样的链表称为双向链表. 双向链表的结构如图所示: 查找元素可以根据元 ...

  5. 【Java】 大话数据结构(1) 线性表之顺序存储结构

     本文根据<大话数据结构>一书,实现了Java版的顺序存储结构. 顺序存储结构指的是用一段地址连续的存储单元一次存储线性表的数据元素,一般用一维数组来实现. 书中的线性表抽象数据类型定义如 ...

  6. 【Java】 大话数据结构(2) 线性表之单链表

    本文根据<大话数据结构>一书,实现了Java版的单链表. 每个结点中只包含一个指针域的链表,称为单链表. 单链表的结构如图所示: 单链表与顺序存储结构的对比: 实现程序: package ...

  7. 【Java】 大话数据结构(3) 线性表之静态链表

    本文根据<大话数据结构>一书,实现了Java版的静态链表. 用数组描述的链表,称为静态链表. 数组元素由两个数据域data和cur组成:data存放数据元素:cur相当于单链表中的next ...

  8. 【Java】 大话数据结构(6) 栈的顺序与链式存储

    本文根据<大话数据结构>一书,实现了Java版的栈的顺序存储结构.两栈共享空间.栈的链式存储机构. 栈:限定仅在表尾进行插入和删除操作的线性表. 栈的插入(进栈)和删除(出栈)操作如下图所 ...

  9. 【Java】 大话数据结构(7) 循环队列和链队列

    本文根据<大话数据结构>一书,实现了Java版的循环队列.链队列. 队列:只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 1.循环队列 队列的顺序储存结构:用数组存储队列,引入 ...

随机推荐

  1. 烟大 Contest1024 - 《挑战编程》第一章:入门 Problem E: Graphical Editor(模拟控制台命令形式修改图形)

    Problem E: Graphical Editor Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 2  Solved: 2[Submit][Statu ...

  2. MATLAB信号与系统分析(一)——连续时间信号与系统的时域分析

    一.连续时间信号的表示: 1.向量表示法: 在MATLAB中,是用连续信号在等时间间隔点的样值来近似表示连续信号,当取样时间间隔足够小时,这些离散的样值就能较好地近似出连续信号. 对于连续时间信号f( ...

  3. DedeCMS让{dede:list}标签支持weight权重排序

    1.找到"根目录\include\arc.listview.class.php"文件. 2.修改代码:在文件第727行处添加按weight排序判断代码(红色部分为新添加代码). / ...

  4. 二分查找法 java

    前几天去面试,让我写二分查找法,真是哔了狗! 提了离职申请,没事写写吧! 首先二分查找是在一堆有序的序列中找到指定的结果. public class Erfen { public static int ...

  5. 用indexOf判断设备是否是PC端?

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. DFS POJ 2362 Square

    题目传送门 /* DFS:问能否用小棍子组成一个正方形 剪枝有3:长的不灵活,先考虑:若根本构不成正方形,直接no:若第一根比边长长,no 这题是POJ_1011的精简版:) */ #include ...

  7. BZOJ3658 : Jabberwocky

    考虑将某线段下方的点取走: 将所有点从低到高排序 每扫描到一条水平线,对于上面每个点,找到它下面同色的前驱后继,统计中间点的个数 然后再把线上所有点插入数据结构中 最后再统计相邻的同色的点之间的点个数 ...

  8. RETINA显示屏下ICON优化方法

    便于理解,先来了解几个名词: dpi(dots per inch),每英寸的点数,用来测量任何设备的硬件分辨率.一个21”的屏幕可以拥有1680 X 1050 的分辨率,27”的屏幕也可以拥有相同的分 ...

  9. HDU 4419 Colourful Rectangle(线段树+扫描线)

    题目链接 主要是pushup的代码,其他和区间更新+扫描线差不多. 那个区间如果要再刷一层x,那么sum[x][rt] = que[r+1] - que[l];但是如果原本有颜色为i,颜色将会变成i| ...

  10. c++ namespace的使用

    ** namespace:命名空间就是为解决C++中的变量.函数的命名冲突而服务的. ** namespace定义的格式基本格式是: namespace identifier {    entitie ...