双向链表:
数据结构示意图1.1.1如下:
图1.1.1 链表节点结构示意图
让代码来讲话吧:
Structure.h
#ifndef DATA_STRUCTURE_DNLIST_STRUCTURE_H
#define DATA_STRUCTURE_DNLIST_STRUCTURE_H
#include <iostream>
using namespace std;
/*-------------------1.链表----------------------*/
#define Mark 0 //宏定义链表Mark的起始值,更改此处会产生联动效果
#define HeadM pHead->mark = Mark //设置链表头结点pHead的mark为0
// (1)单向链表:
// (2)单向循环链表:
typedef struct SCNode {
int date; //数据
unsigned int mark; //第mark个节点
SCNode *pNext; //节点尾指针
} SN, //单向
SCN; //单向循环
//二者数据结构相同
//=============================================//
// (3)双向链表:
// (4)双向循环链表:
typedef struct DNode {
int date; //数据
unsigned int mark; //第mark个节点
DNode *pPrev; //节点头指针
DNode *pNext; //节点尾指针
} DN, //双向
DCN; //双向循环
//二者数据结构相同
/*-------------------1.链表----------------------*/
#endif //DATA_STRUCTURE_DNLIST_STRUCTURE_H
Structure.cpp
#include "Structure.h"
#include "Operation.h"
/*-------------------1.链表----------------------*/
// (3)双向链表:
//遍历整个链表,返回尾节点
DN *FindTail(DN *pHead) {
while (pHead->pNext != nullptr)pHead = pHead->pNext;
return pHead;
}
//查找任意节点[调用此函数前,需确保List中mark的顺序性]
DN *FindNode(DN *pHead, int pos) {
while (pos-Mark != pHead->mark) {
pHead = pHead->pNext;
}
return pHead;
}
//规律化NODE[mark]
DN *RegularMark(DN *pHead) {
DN *pNTemp = pHead;
int count = Mark;
do {
pHead->mark = count++;
}while (nullptr!= (pHead = pHead->pNext));
return pNTemp;
}
/*-------------------1.链表----------------------*/
Operation.h
#ifndef DATA_STRUCTURE_DNLIST_OPERATION_H
#define DATA_STRUCTURE_DNLIST_OPERATION_H
#include "Structure.h"
/*-------------------1.链表----------------------*/
// (1)单向链表:
// a.创建链表:
// b.插入节点:1.头插 2.尾插 3.中间插
// c.删除节点:1.头删 2.尾删 3.中间删
// d.打印链表:
// (2)单向循环链表:
// a.创建链表:
// b.插入节点:1.头插 2.尾插 3.中间插
// c.删除节点:1.头删 2.尾删 3.中间删
// d.打印链表:
//=============================================//
// (3)双向链表:
DN *FindTail(DN *pHead); //遍历整个链表,返回尾节点
DN *FindNode(DN *pHead, int pos); //查找任意节点[调用此函数前,需确保List中mark的顺序性]
DN *RegularMark(DN *pHead); //规律化NODE[mark]
// a.创建链表:
DN *CreateHead();
// b.插入节点:1.头插 2.尾插 3.中间插
DN *InsertHead(DN *pHead); //1.头插
DN *InsertTail(DN *pHead); //2.尾插
DN *InsertMiddle(DN *pHead, int pos); //3.中间插
// c.删除节点:1.头删 2.尾删 3.中间删
DN *DeleteHead(DN *pHead); //1.头插
DN *DeleteTail(DN *pHead); //2.尾插
DN *DeleteMiddle(DN *pHead, int pos); //3.中间插
// d.打印链表:先正序输出,后逆序输出链表[以pNext方向为正,pPrev方向为逆向]
unsigned int DisplayList(DN *pHead);
// (4)双向循环链表:
// a.创建链表:
// b.插入节点:1.头插 2.尾插 3.中间插
// c.删除节点:1.头删 2.尾删 3.中间删
// d.打印链表:
/*-------------------1.链表----------------------*/
#endif //DATA_STRUCTURE_DNLIST_OPERATION_H
Operation.cpp
#include "Operation.h"
/*-------------------1.链表----------------------*/
// (1)单向链表:
// a.创建链表:
// b.插入节点:1.头插 2.尾插 3.中间插
// c.删除节点:1.头删 2.尾删 3.中间删
// d.打印链表:
// (2)单向循环链表:
// a.创建链表:
// b.插入节点:1.头插 2.尾插 3.中间插
// c.删除节点:1.头删 2.尾删 3.中间删
// d.打印链表:
// (3)双向链表:
/*在此注释中以pNext方向为向后;
* 以pPrev方向为向前。
* */
// a.创建链表:
DN *CreateHead() {
DN *pHead = new DNode();
pHead->pNext = nullptr; //节点尾指向空[不循环]
pHead->pPrev = nullptr; //节点头指向空[不循环]
HeadM; //设置HeadMark
cout << "Enter a value of the ListHead[" << pHead->mark << "]:" << endl;
cin >> pHead->date; //键入头结点存储数据
return pHead;
}
// b.插入节点:1.头插 2.尾插 3.中间插
DN *InsertHead(DN *pHead) {
int TpMark = pHead->mark;
char ch = 'y';
while ('y' == ch || 'Y' == ch) {
DN *newNode = new DNode();
//if (nullptr == newNode){perror("内存申请失败");exit(-1);}
cout << "Enter a value of the node[" << ++TpMark << "]:" << endl;
newNode->mark = TpMark; //设置newNode的mark
cin >> newNode->date; //键入存储的值
pHead->pPrev = newNode; //使原链表的pPrev指针指向newNode[将NewNode插入pHead前,链接好向前的结构]
newNode->pNext = pHead; //使NewNode的尾指针pNext指向pHead[将NewNode插入pHead前,链接好向后的结构]
pHead = newNode; //将NewNode赋值给pHead[前移指针pHead,保证pHead始终指向链表头]
cout << "Enter choice inserter(y/n):" << endl;
cin >> ch;
}
//RegularMark(pHead);
return pHead;
}
DN *InsertTail(DN *pHead) {
DN *LTail = pHead;
char ch = 'Y';
LTail = FindTail(LTail); //调用FindTail找到尾节点指针,赋给LTail
int TpMark = LTail->mark; //记录尾节点Mark
while (ch == 'y' || ch == 'Y') {
DN *newNode = new DNode();
//if (nullptr == newNode){perror("内存申请失败");exit(-1);}
cout << "Enter a value of the node[" << ++TpMark << "]:" << endl;
newNode->mark = TpMark; //写入TpMark到newNode Mark中
cin >> newNode->date;
LTail->pNext = newNode; //将尾节点LTail的pNext指针指向NewNode[链接NewNode到List尾部,链接好向后的结构]
newNode->pPrev = LTail; //将新节点newNode的pPrev指针指向LTail[链接NewNode到List尾部,链接好向前的结构]
LTail = newNode; //将NewNode赋给LTail[使LTail始终指向尾节点]
cout << "Enter choice inserter(y/n):" << endl;
cin >> ch;
}
//RegularMark(pHead);
return pHead;
}
DN *InsertMiddle(DN *pHead, int pos) {
DN *pNTemp01 = pHead, *pNTemp02 = nullptr;
pos--;
char ch = 'y';
//int count = 0;
RegularMark(pHead);
pNTemp01 = FindNode(pNTemp01, pos); // 找到插入节点的前一个节点pNTemp01
pNTemp02 = pNTemp01->pNext; // 找到应该插入的位置节点pNTemp02
while (ch == 'y' || ch == 'Y') {
DN *newNode = new DNode();
//if (nullptr == newNode){perror("内存申请失败");exit(-1);}
newNode->mark = pNTemp01->mark;
newNode->mark++;
cout << "Enter a value of the inserted node:" << endl;
cin >> newNode->date;
pNTemp01->pNext = newNode; // 将前节点pNTemp01的pNext指针指向新节点newNode[链接NewNode到pNTemp01后,链接好向后的结构]
newNode->pPrev = pNTemp01; // 将新节点newNode的pPrev指针指向前节点pNTemp01[链接NewNode到pNTemp01后,链接好向前的结构]
newNode->pNext = pNTemp02; // 将pNTemp02赋给newNode->pNext[将pNTemp02链接在newNode后]
pNTemp02->pPrev = newNode; // 将newNode赋给pNTemp02->pPrev[将newNode链接在pNTemp02前]
pNTemp01 = pNTemp01->pNext; // 将pNTemp01后移一位指向newNode
//while (nullptr != (pNTemp01 = pNTemp01->pNext))++pNTemp01->mark;
cout << "Enter choice of inserter(y/n):" << endl;
cin >> ch;
//count++;
}
//while (nullptr != (pNTemp01 = pNTemp01->pNext))pNTemp01->mark += count;
RegularMark(pHead);
return pHead;
}
// c.删除节点:1.头删 2.尾删 3.中间删
DN *DeleteHead(DN *pHead) {
char ch = 'y';
DN *pNTemp = pHead;
while ('y' == ch || 'Y' == ch) {
pNTemp = pHead; //暂存pHead
pHead = pHead->pNext; //将pHead指向下一个节点
pHead->pPrev = nullptr; //规避野指针
cout << "Enter choice of deleting head node (y/n):" << endl;
cin >> ch;
if (pHead->pNext!= nullptr ) { //确保DisplayList函数正常调用
DisplayList(pHead);
delete pNTemp; //释放内存
} else {
cout << "Can't remove the last node!" << endl;
return pHead;
}
}
//RegularMark(pHead);
return pHead;
}
DN *DeleteTail(DN *pHead) { //(1)不断循环寻找最后节点删除
//(1)
char ch = 'y';
unsigned int count = 0;
DN *pNTemp = pHead, *pNTemp01 = nullptr, *pNTemp02 = nullptr;
RegularMark(pHead);
while ('y' == ch || 'Y' == ch) {
count = DisplayList(pNTemp);
if (pHead->pNext == nullptr) { //确保内存安全
cout << "Can't remove the last node!" << endl;
break;
}
pNTemp01 = FindNode(pNTemp, count - 2); // 找到尾节点的前一个节点
pNTemp02 = pNTemp01->pNext; // 暂存尾节点
pNTemp01->pNext = nullptr; // 使得原尾节点前一个节点变为尾节点
delete pNTemp02; // 释放原尾节点内存
pNTemp02 = nullptr; // 避免pNTemp02野指针
cout << "Enter choice of deleting tail node (y/n):" << endl;
cin >> ch;
}
//RegularMark(pHead);
return pHead;
}
DN *DeleteMiddle(DN *pHead, int pos) {
DN *pNTemp01 = pHead, *pNTemp02 = nullptr, *pNTemp03 = nullptr;
pNTemp01 = FindNode(pNTemp01, pos - 2); // 前节点指针
pNTemp02 = pNTemp01->pNext; // 中结点指针
pNTemp03 = pNTemp02->pNext; // 尾结点指针
pNTemp01->pNext = pNTemp03; // 前后链接
pNTemp03->pPrev = pNTemp01; // 后前连接
delete pNTemp02; // 删除中间节点
pNTemp02 = nullptr; // 避免pNTemp02野指针
//RegularMark(pHead);
return pHead;
}
// d.打印链表:
unsigned int DisplayList(DN *pHead) {
DN *LTail = FindTail(pHead);
unsigned int count = 0;
cout<<"Forward display list:"<<endl;
do {
cout << "NODE[" << pHead->mark << "] = " << pHead->date << endl;
count++;
} while ((pHead = pHead->pNext) != nullptr);
cout<<"\nInverted display list:"<<endl;
do {
cout << "NODE[" << LTail->mark << "] = " << LTail->date << endl;
} while ((LTail = LTail->pPrev) != nullptr);
return count;
}
main.cpp
#include "Structure.h"
#include "Operation.h"
int main() {
DN *pHead = nullptr; //创建单向链表类型的头指针pHead,初始化为空指针nullptr
pHead = CreateHead(); //创建头结点,pHead存储头结点的位置(存储头结点的位置)
// pHead = InsertHead(pHead); //调用头插
pHead = InsertTail(pHead); //调用尾插
// pHead = InsertMiddle(pHead,2); //调用中间插入
// pHead = DeleteHead(pHead); //调用头删
// pHead = DeleteTail(pHead); //调用尾删
pHead = DeleteMiddle(pHead,2); //调用中间删除[至少三个节点]
int count = DisplayList(pHead);
cout << "\nCount of list = " << count << "\nThe tail date of list = " << FindTail(pHead)->date << endl;
delete pHead; //释放pHead
return 0;
}
测试结果如下图1.1.2:
图1.1.2 测试结果