学习完双链表做一下记录以防忘记,有错误希望大家可以多多指正。
这段代码首先定义了一个双链表的结构体 Lnode
,其中包含数据 a
以及指向前驱和后继节点的指针 prev
和 next
。
接下来,实现了一系列双链表的操作函数:
ListInit
用于初始化双链表的头节点。ListIsEmpty
用于判断双链表是否为空。ListPrint
用于打印双链表中的元素。ListLength
用于计算双链表的长度。ListCreatH
以头插法创建双链表。ListCreatR
以尾插法创建双链表。ListInsert
实现向指定位置插入元素。ListSearchByValue
按值查找链表中的节点。ListSearchByPosition
按位置查找链表中的节点。ListDel
删除指定位置的节点。ClearList
用于释放整个双链表的内存。
1. 创建结构体:
//创建结构体
typedef struct Lnode{
int a;
Lnode* prev, * next;
}Lnode;
2. 初始化链表
// 初始化链表
void ListInit(Lnode** L) {
// 为头节点分配内存
(*L) = (Lnode*)malloc(sizeof(Lnode));
// 初始化头节点的指针
(*L)->next = NULL;
(*L)->prev = NULL;
}
3. 打印链表
// 打印链表
void ListPrint(Lnode** L) {
Lnode* p = (*L);
// 遍历链表并打印节点的值
while (p->next!= NULL) {
cout << p->next->a << " ";
p = p->next;
}
cout << endl;
}
4. 判断链表是否为空
// 判断链表是否为空
bool ListIsEmpty(Lnode** L) {
return (*L)->next == NULL;
}
5. 求双链表的长度
// 求双链表的长度
int ListLength(Lnode** L) {
int length = 0;
Lnode* p = (*L)->next;
while (p != NULL) {
length++;
p = p->next;
}
return length;
}
6. 头插法建立双链表
// 头插法建立双链表
bool ListCreatH(Lnode** L){
int x;
cout << "请输入数据(输入 0 结束):" << endl;
cin >> x;
// 循环输入并插入节点
while (x!= 0) {
Lnode* N = (Lnode*)malloc(sizeof(Lnode));
N->a = x;
N->next=(*L)->next;
// 如果头节点的下一个节点不为空,更新其前驱指针
if ((*L)->next!=NULL) {
(*L)->next->prev = N;
}
N->prev = (*L);
(*L)->next = N;
cin >> x;
}
return true;
}
7. 尾插法建立双链表
// 尾插法建立双链表
bool ListCreatR(Lnode** L) {
int x;
cout << "请输入数据(输入 0 结束):" << endl;
cin >> x;
Lnode* R = (*L);
// 循环输入并在尾部插入节点
while (x!= 0) {
Lnode* N = (Lnode*)malloc(sizeof(Lnode));
N->a = x;
R->next = N;
N->prev = R;
N->next = NULL;
R = N;
cin >> x;
}
R = NULL;
return true;
}
8. 按值查找
// 按值查找
Lnode* ListSearchByValue(Lnode** L, int value) {
Lnode* p = (*L)->next;
while (p != NULL) {
if (p->a == value) {
return p;
}
p = p->next;
}
return NULL;
}
9. 按位查找
Lnode* ListSearchByPosition(Lnode** L, int position) {
if (position <= 0) {
return NULL;
}
Lnode* p = (*L)->next;
int count = 1;
while (p != NULL && count < position) {
p = p->next;
count++;
}
if (count == position) {
return p;
}
return NULL;
}
10. 数据插入
// 数据插入
bool ListInsert(Lnode** L, int i, int e) {
// 如果插入位置不合法,返回 false
if (i <= 0) return false;
Lnode* P = (*L);
// 找到要插入的位置
while (--i){
if (P == NULL) return false;
P = P->next;
}
Lnode* N = (Lnode*)malloc(sizeof(Lnode));
N->a = e;
// 调整指针完成插入
N->next = P->next;
N->prev = P;
if (P->next!= NULL) {
P->next->prev = N;
}
P->next = N;
return true;
}
11. 删除节点
// 删除节点
bool ListDel(Lnode** L, int i, int& e) {
// 如果删除位置不合法,返回 false
if (i <= 0) return false;
Lnode* P = (*L);
// 找到要删除节点的前一个节点
while (--i) {
if (P == NULL) return false;
P = P->next;
}
Lnode* temp = P->next;
// 调整指针完成删除
if (P->next->next!= NULL) {
P->next->next->prev = P;
}
P->next = P->next->next;
free(temp);
return true;
}
12. 删除整条链表
// 删除整条链表
void ClearList(Lnode** L) {
Lnode* P = (*L);
// 逐个释放链表节点内存
while (P!= NULL) {
(*L) = (*L)->next;
free(P);
P = (*L);
}
(*L) = NULL;
}
在 main
函数中,我们首先初始化一个双链表,并使用尾插法创建链表。然后进行了删除节点、打印链表、获取链表长度、判断链表是否为空、按位置查找节点等操作。
测试代码:
#include <iostream>
using namespace std;
//创建结构体
typedef struct Lnode{
int a;
Lnode* prev, * next;
}Lnode;
// 初始化链表
void ListInit(Lnode** L) {
// 为头节点分配内存
(*L) = (Lnode*)malloc(sizeof(Lnode));
// 初始化头节点的指针
(*L)->next = NULL;
(*L)->prev = NULL;
}
// 判断链表是否为空
bool ListIsEmpty(Lnode** L) {
return (*L)->next == NULL;
}
// 打印链表
void ListPrint(Lnode** L) {
Lnode* p = (*L);
// 遍历链表并打印节点的值
while (p->next != NULL) {
cout << p->next->a << " ";
p = p->next;
}
cout << endl;
}
// 求双链表的长度
int ListLength(Lnode** L) {
int length = 0;
Lnode* p = (*L)->next;
while (p != NULL) {
length++;
p = p->next;
}
return length;
}
// 头插法建立双链表
bool ListCreatH(Lnode** L) {
int x;
cout << "请输入数据(输入 0 结束):" << endl;
cin >> x;
// 循环输入并插入节点
while (x != 0) {
Lnode* N = (Lnode*)malloc(sizeof(Lnode));
N->a = x;
N->next = (*L)->next;
// 如果头节点的下一个节点不为空,更新其前驱指针
if ((*L)->next != NULL) {
(*L)->next->prev = N;
}
N->prev = (*L);
(*L)->next = N;
cin >> x;
}
return true;
}
// 尾插法建立双链表
bool ListCreatR(Lnode** L) {
int x;
cout << "请输入数据(输入 0 结束):" << endl;
cin >> x;
Lnode* R = (*L);
// 循环输入并在尾部插入节点
while (x != 0) {
Lnode* N = (Lnode*)malloc(sizeof(Lnode));
N->a = x;
R->next = N;
N->prev = R;
N->next = NULL;
R = N;
cin >> x;
}
// 这一步将 R 置为 NULL 并非必要
R = NULL;
return true;
}
// 数据插入
bool ListInsert(Lnode** L, int i, int e) {
// 如果插入位置不合法,返回 false
if (i <= 0) return false;
Lnode* P = (*L);
// 找到要插入的位置
while (--i) {
if (P == NULL) return false;
P = P->next;
}
Lnode* N = (Lnode*)malloc(sizeof(Lnode));
N->a = e;
// 调整指针完成插入
N->next = P->next;
N->prev = P;
if (P->next != NULL) {
P->next->prev = N;
}
P->next = N;
return true;
}
// 按值查找
Lnode* ListSearchByValue(Lnode** L, int value) {
Lnode* p = (*L)->next;
while (p != NULL) {
if (p->a == value) {
return p;
}
p = p->next;
}
return NULL;
}
// 按位查找
Lnode* ListSearchByPosition(Lnode** L, int position) {
if (position <= 0) {
return NULL;
}
Lnode* p = (*L)->next;
int count = 1;
while (p != NULL && count < position) {
p = p->next;
count++;
}
if (count == position) {
return p;
}
return NULL;
}
// 删除节点
bool ListDel(Lnode** L, int i, int& e) {
// 如果删除位置不合法,返回 false
if (i <= 0) return false;
Lnode* P = (*L);
// 找到要删除节点的前一个节点
while (--i) {
if (P == NULL) return false;
P = P->next;
}
Lnode* temp = P->next;
e = temp->a;
// 调整指针完成删除
if (P->next->next != NULL) {
P->next->next->prev = P;
}
P->next = P->next->next;
free(temp);
return true;
}
// 删除整条链表
void ClearList(Lnode** L) {
Lnode* P = (*L);
// 逐个释放链表节点内存
while (P != NULL) {
(*L) = (*L)->next;
free(P);
P = (*L);
}
(*L) = NULL;
}
int main() {
Lnode* L;
ListInit(&L);
//尾插法创建链表
ListCreatR(&L);
cout << "您创建的链表是:";
ListPrint(&L);
int e;
ListDel(&L, 1, e);
cout << "删除第一个节点后为:";
ListPrint(&L);
cout << "删除的节点是:" << e << endl;
cout << "链表长度为:" << ListLength(&L) << endl;
cout <<"是否为空:"<< (bool)ListIsEmpty(&L) << endl;
Lnode* P = ListSearchByPosition(&L, 3);
if (P != NULL) cout << "第三个元素为:" << P->a;
else cout << "未查询到节点三" << endl;
ClearList(&L);
return 0;
}
输出示例: