双链表是在单链表的基础上提出来的另一种链表形式。顾名思义,单链表只有一个指针,而双链表有两个指针:一个前驱指针,一个后继指针。双链表的每一个节点仍然是一个结构体,与单链表唯一不同的是,节点额外多了一个指向前节点的指针,这是为了方便有时候需要倒序扫描链表。双链表有两种形式:一般的双链表和循环双链表。如图:
循环双链表只是把头节点与尾节点相互连接起来了,如图:
下面我们基于单链表(见我的另一篇文章:http://blog.csdn.net/wonggonghong/article/details/21527577),首先实现一个一般的双链表。在下一篇文章里,我们再实现一个双向循环链表。事实上,代码的改动并不是很大。
类似地,我们在<List.h>头文件里声明双链表结构:
#include "list.h"
//创建一个非循环的双链表结构,包含一些常见的操作
#ifndef _List_H_
#define _List_H_
#include <iostream>
struct Double_Node{
int element; //节点存储信息可以根据需要修改!
Double_Node* previous;
Double_Node* next;
};
Double_Node* CreateLists(int X); //创建一个值为X的双链表节点
void DeleteLists(Double_Node* head); //删除表头为head的该链表
bool IsFirst(Double_Node* P);
bool IsLast(Double_Node* P);
Double_Node* FindLeft(int X, Double_Node* P); //从P开始向P的左边进行查找
Double_Node* FindRight(int X, Double_Node* P); //从P开始向P的右边进行查找
Double_Node* Find(int X, Double_Node* head); //从整个双链表中查找
void Delete(int X, Double_Node* Lists);
void Insert(Double_Node* P, int X); //在节点P后面插入X
void OutputLists(Double_Node* head); //输出链表中所有元素的值
#endif
然后,在<List.cpp>文件里实现双链表操作(注意与单链表略有些不同):
#include "list.cpp"
#include "list.h"
#include <assert.h>
Double_Node* CreateLists(int X)
{
Double_Node* head = new Double_Node;
head->previous = head->next = NULL;
head->element = X;
return head;
}
void DeleteLists(Double_Node* head)
{
assert(!head->previous); //验证head为表头!
Double_Node* P = head, *temp;
while(P)
{
temp = P->next;
if(temp)
{
temp->previous = NULL;
P->next = NULL;
}
delete P;
P = temp;
}
}
bool IsFirst(Double_Node* P)
{
return P->previous == NULL;
}
bool IsLast(Double_Node* P)
{
return P->next == NULL;
}
Double_Node* FindLeft(int X, Double_Node* P)
{
Double_Node* temp = P;
while(temp && temp->element!=X)
temp = temp->previous;
return temp;
}
Double_Node* FindRight(int X, Double_Node* P)
{
Double_Node* temp = P;
while(temp && temp->element!=X)
temp = temp->next;
return temp;
}
Double_Node* Find(int X, Double_Node* P)
{
Double_Node* temp = FindLeft(X,P);
return temp?temp:FindRight(X,P);
}
void Delete(int X, Double_Node* Lists)
{
Double_Node* temp = Find(X,Lists); //如果没找到X,则temp=NULL
if(temp)
{
if(temp->previous)
temp->previous->next = temp->next;
if(temp->next)
temp->next->previous = temp->previous;
temp->previous = temp->next = NULL;
delete temp;
}
}
void Insert(Double_Node* P, int X)
{
Double_Node* tempX = new Double_Node;
tempX->element = X;
tempX->previous = P;
tempX->next = P->next;
if(P->next)
P->next->previous = tempX;
P->next = tempX;
}
void OutputLists(Double_Node* head)
{
assert(!head->previous);
Double_Node* P = head;
while(P)
{
std::cout<<P->element<<" ";
P = P->next;
}
std::cout<<std::endl;
}
最后,同样用一段main代码验证一下:
#include <iostream>
#include "list.h"
using namespace std;
int main()
{
int Data[10] = {1,3,4,6,0,2,5,8,12,13};
Double_Node* head = CreateLists(1);
Double_Node* P = head;
for(int i=1;i<10;i++)
{
Insert(P,Data[i]);
P = P->next;
}
cout<<"打印出(非循环)双链表的所有元素:\n";
OutputLists(head);
if(IsFirst(head) && !IsFirst(P))
cout<<"节点head是双链表的表头,节点值为:"<<head->element<<endl;
else
cout<<"IsFirst函数有错误!!!\n";
if(!IsLast(head) && IsLast(P))
cout<<"节点P是表尾,值为:"<<P->element<<endl;
else
cout<<"IsLast函数有错误!!!\n";
P = P->previous->previous;
if(FindLeft(12,P))
cout<<"FindLeft函数错误!\n";
else if(!FindRight(12,P))
cout<<"FindRight函数错误!\n";
else if(!Find(4,P) || !Find(13,P))
cout<<"Find函数错误!\n";
else
cout<<"FindLeft、FindRight、Find函数都没有问题!\n";
Delete(8,P);
cout<<"删除节点8后,再打印出(非循环)双链表的所有元素:\n";
OutputLists(head);
return 0;
}
结果如下: