** 双向链表的结构如下:**
typedef struct _dbLinkList{
type data;
_dbLinkList* pre;
_dbLinkList* next;
}dbLinkList,dbLinkNode;
**双向链表的特性:**由结构可以看出,双向链表继承了单向链表的特性同时,其构成相对于单向链表,多了一个指向前一个元素的pre指针,具有了逆向追溯性。
**函数调用接口:**其结构函数初始化、尾部插入、查询元素、增加元素、销毁链表同单向链表,
但是前插法、删除元素接口函数有些不一样。
具体的详见接口函数代码注释。
bool dbLinkListInsertFront(dbLinkList*& link, dbLinkList* &node) {
if (!link || !node) return false;
if (!link->next) {//链表为空的情况
node->next = NULL;
node->pre = link;
link->next = node;
}
else {//第二个结点靠头结点来外推,所以必须得先将第二个结点关联的指针赋值,才不会改变原有的值
node->next = link->next;//将新结点指向第二个结点
link->next->pre = node; //先将第二个结点指向新结点
link->next = node;//将首结点指向新结点
node->pre = link; //将新结点指向首结点
}
return true;
}
以上是前插法的调用函数区分为空链表插入和非空链表插入,同时在非空链表插入时,连接前后指针的顺序非常重要,必须将外推的结点先赋值。
以下是删除元素函数,和前插法函数有些类似,分为删除的结点是尾结点和非尾结点两种情况。
bool dbLinkListDeleteEle(dbLinkList* &link, int i) {
if (!link) return false;
dbLinkList* p = link;
int pos = 0;
while (p && pos < i) {
p = p->next;
pos++;
}
if (!p || pos > i) return false;
if (!p->next) {//删除的是尾结点
p->pre->next = NULL;
}
else {//删除的是非尾结点
p->next->pre = p->pre;
p->pre->next = p->next;
}
delete p;
return true;
}
其他通用的函数和调试代码如下(含前面的接口程序,亲测可用)
#include<Windows.h>
#include<iostream>
using namespace std;
typedef struct _dbLinkList {
int data;
_dbLinkList* pre;
_dbLinkList* next;
}dbLinkListNode,dbLinkList;
//函数实现
bool initdbLinkList(dbLinkList* &link);//双向链表初始化
bool dbLinkListInsertFront(dbLinkList*& link, dbLinkList* &node);//链表前插法
bool dbLinkListPrint(dbLinkList*& link);//打印链表
bool dbLinkListInsertBack(dbLinkList* &link,dbLinkList* &node);//链表尾插法
bool dbLinkListInsert(dbLinkList* &link,int i,dbLinkList* &node);//任意位置插入
bool dbLinkListGetEle(dbLinkList*& link, int i, dbLinkList*& node);//获取第i个位置的元素
//根据需要更改要查询的数据类型
bool dbLinkListFindEle(dbLinkList*& link, int e);//查询是否有元素e
bool dbLinkListDeleteEle(dbLinkList*& link, int i);//删除第i个位置的数据
void dbLinkListDestroy(dbLinkList*& link);//销毁链表
int main() {
dbLinkList* link;
dbLinkListNode* node;
initdbLinkList(link);
int cout;
std::cout << "采用前插法插入数据,请输入要插入的个数:" << std::endl;
cin >> cout;
for (int i = 0; i < cout; i++) {
node = new dbLinkListNode;
cin >> node->data;
dbLinkListInsertFront(link, node);
}
dbLinkListPrint(link);
std::cout << "**************采用尾插法插入数据,请输入要插入的个数:***********" << std::endl;
cin >> cout;
for (int i = 0; i < cout; i++) {
node = new dbLinkListNode;
cin >> node->data;
dbLinkListInsertBack(link, node);
}
dbLinkListPrint(link);
std::cout << "**************任意位置插入数据,请输入要插入的位置和数据:***********" << std::endl;
cin >> cout;
node = new dbLinkListNode;
cin >> node->data;
if (dbLinkListInsert(link, cout, node)) {
std::cout << "插入成功!" << std::endl;
dbLinkListPrint(link);
}
else {
std::cout << "插入失败!" << std::endl;
}
std::cout <<endl<< "**************获取指定位置的数据,请输入要获取的位置:***********" << std::endl;
cin >> cout;
node = new dbLinkListNode;
if (dbLinkListGetEle(link, cout, node)) {
std::cout << "获取成功!第"<<cout<<"位的数据是:"<<node->data << std::endl;
}
else {
std::cout << "获取失败!" << std::endl;
}
std::cout << endl << "**************查询是否有指定的数据***********" << std::endl;
cout = 4;
if (dbLinkListFindEle(link,cout)) {
std::cout << "查询成功!" << std::endl;
}
else {
std::cout << "查询失败!" << std::endl;
}
std::cout << endl << "**************删除指定位置的数据,请输入位置***********" << std::endl;
cin>>cout;
if (dbLinkListDeleteEle(link, cout)) {
std::cout << "删除成功!" << std::endl;
dbLinkListPrint(link);
}
else {
std::cout << "删除失败!" << std::endl;
}
dbLinkListDestroy(link);
system("pause");
return 0;
}
bool initdbLinkList(dbLinkList* &link) {
link = new dbLinkList;
if (!link) return false;
link->pre = NULL;
link->next = NULL;
link->data = -1;
return true;
}
bool dbLinkListInsertFront(dbLinkList*& link, dbLinkList* &node) {
if (!link || !node) return false;
if (!link->next) {//链表为空的情况
node->next = NULL;
node->pre = link;
link->next = node;
}
else {//第二个结点靠头结点来外推,所以必须得先将第二个结点关联的指针赋值,才不会改变原有的值
node->next = link->next;//将新结点指向第二个结点
link->next->pre = node; //先将第二个结点指向新结点
link->next = node;//将首结点指向新结点
node->pre = link; //将新结点指向首结点
}
return true;
}
bool dbLinkListPrint(dbLinkList*& link) {
if (!link) return false;
dbLinkList* p = link;
while (p->next) {
p = p->next;
cout << p->data << " ";
}
cout << endl;
cout << "逆向打印双向链表!" << endl;
while (p!=link) {
cout << p->data << " ";
p = p->pre;
}
return true;
}
bool dbLinkListInsertBack(dbLinkList*& link, dbLinkList*& node) {
if (!link || !node) return false;
dbLinkList* p = link;
while (p->next != NULL) {
p = p->next;
}
p->next = node;
node->pre = p;
node->next = NULL;
return true;
}
bool dbLinkListInsert(dbLinkList*& link, int i, dbLinkList*& node) {
if (!link || !node) return false;
dbLinkList* p = link;
int pos = 0;
while (p && pos < i - 1) {//找到第i-1个结点
p = p->next;
pos++;
}
if (pos > i - 1 || !p) return false;
p->next->pre = node;
node->next = p->next;
p->next = node;
node->pre = p;
return true;
}
bool dbLinkListGetEle(dbLinkList*& link, int i, dbLinkList*& node) {
if (!link || !node) return false;
dbLinkList* p = link;
int pos = 0;
while (p && pos < i) {
p = p->next;
pos++;
}
if (!p || pos > i) return false;
node = p;
node->next = p->next;
node->pre = p->pre;
return true;
}
bool dbLinkListFindEle(dbLinkList*& link, int e) {
if (!link) return false;
dbLinkList* p = link;
while (p && p->data != e) {
p = p->next;
}
if (!p || p==link) return false;
else return true;
}
bool dbLinkListDeleteEle(dbLinkList* &link, int i) {
if (!link) return false;
dbLinkList* p = link;
int pos = 0;
while (p && pos < i) {
p = p->next;
pos++;
}
if (!p || pos > i) return false;
if (!p->next) {//删除的是尾结点
p->pre->next = NULL;
}
else {//删除的是非尾结点
p->next->pre = p->pre;
p->pre->next = p->next;
}
delete p;
return true;
}
void dbLinkListDestroy(dbLinkList*& link) {
if (!link) return;
dbLinkList* p = link;
while (p->next) {
link = p->next;
delete p;
p = link;
}
delete p;
}