实验题3:实现双链表的各种基本运算的算法
题目描述
编写一个程序dlinklist.cpp,实现双链表的各种基本运算和整体建表算法(偏
双链表的元素类型ElemType为int),并在此基础上设计一个程序exp2-3.cpp完成以
功能。
(1)初始化双链表h。
(2)依次采用尾插法插入元素a、b、c、d、e。
(3)输出双链表h。
(4)输出双链表h的长度。
(5)判断双链表h是否为空。
(6)输出双链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素的位置上插入元素f。
(9)输出双链表h。
(10)删除双链表h的第3个元素。
(11)输出双链表h。
(12)释放双链表h。
dlinklist.cpp程序,其中包含如下函数。
· InitList(DLinkNode *&L):初始化双链表L。
· DestroyList(DLinkNode*L):释放双链表L。
·ListEmpty(DLinkNode*L):判断双链表L是否为空表。
· ListLength(DLinkNode*L):返回双链表L中的元素个数。
· DispList(DLinkNode *L.):输出双链表L。
. GetElem(DLinkNode *I.int i,ElemType &.e):获取双链表L中的第i个元素。
· LocateElem(DLinkNode*L.ElemType e):在双链表L中查找元素e。
. ListInsert(DLinkNode *&1 .. int i.ElemType e):在双链表L的第i个位置上插
入元素e。
· ListDelete(DLinkNode *&L,int i,ElemType &e):从双链表L中删除第i个
元素。
运行代码
dlinklist.cpp
#include <stdio.h>
#include <malloc.h>typedef int ElemType;
typedef struct DNode
{ElemType data;struct DNode* prior;struct DNode* next;
} DLinkNode;// 头插法创建双向链表
void CreateListF(DLinkNode*& L, ElemType a[], int n)
{DLinkNode* s;// 分配头结点空间L = (DLinkNode*)malloc(sizeof(DLinkNode));L->prior = L->next = NULL;for (int i = 0; i < n; i++){// 分配新结点空间s = (DLinkNode*)malloc(sizeof(DLinkNode));s->data = a[i];// 将新结点插入头结点之后s->next = L->next;if (L->next != NULL)L->next->prior = s;L->next = s;s->prior = L;}
}// 尾插法创建双向链表
void CreateListR(DLinkNode*& L, ElemType a[], int n)
{DLinkNode* s, * r;// 分配头结点空间L = (DLinkNode*)malloc(sizeof(DLinkNode));L->prior = L->next = NULL;r = L;for (int i = 0; i < n; i++){// 分配新结点空间s = (DLinkNode*)malloc(sizeof(DLinkNode));s->data = a[i];// 将新结点插入终端结点之后r->next = s;s->prior = r;r = s;}r->next = NULL;
}// 初始化双向链表
void InitList(DLinkNode*& L)
{// 分配头结点空间L = (DLinkNode*)malloc(sizeof(DLinkNode));L->prior = L->next = NULL;
}// 判断链表是否为空
bool ListEmpty(DLinkNode* L)
{return L->next == NULL;
}// 求链表长度
int ListLength(DLinkNode* L)
{DLinkNode* p = L;int i = 0;while (p->next != NULL){i++;p = p->next;}return i;
}// 输出链表
void DispList(DLinkNode* L)
{DLinkNode* p = L->next;while (p != NULL){// 输出当前结点数据printf("%c ", p->data);p = p->next;}printf("\n");
}// 求链表中第 i 个元素的值
bool GetElem(DLinkNode* L, int i, ElemType& e)
{int j = 0;DLinkNode* p = L;if (i <= 0) return false;while (j < i && p != NULL){j++;p = p->next;}if (p == NULL)return false;else{e = p->data;return true;}
}// 查找第一个值域为 e 的元素的序号
int LocateElem(DLinkNode* L, ElemType e)
{int i = 1;DLinkNode* p = L->next;while (p != NULL && p->data != e){i++;p = p->next;}if (p == NULL)return 0;elsereturn i;
}// 在链表中插入第 i 个元素
bool ListInsert(DLinkNode* L, int i, ElemType e)
{int j = 0;DLinkNode* p = L, * s;if (i <= 0) return false;while (j < i - 1 && p != NULL){j++;p = p->next;}if (p == NULL)return false;s = (DLinkNode*)malloc(sizeof(DLinkNode));s->data = e;s->next = p->next;if (p->next != NULL)p->next->prior = s;s->prior = p;p->next = s;return true;
}// 删除链表中第 i 个元素
bool ListDelete(DLinkNode*& L, int i, ElemType& e)
{int j = 0;DLinkNode* p = L, * q;if (i <= 0) return false;while (j < i - 1 && p != NULL){j++;p = p->next;}if (p == NULL)return false;q = p->next;if (q == NULL)return false;e = q->data;p->next = q->next;if (q->next != NULL)q->next->prior = p;free(q);return true;
}// 销毁链表
void DestroyList(DLinkNode*& L)
{DLinkNode* pre = L, * p = pre->next;while (p != NULL){free(pre);pre = p;p = p->next;}free(pre);
}
Excp2-3.cpp
#include <stdio.h>
#include <stdlib.h>
#include "dlinklist.cpp"int main() {DLinkNode* h;ElemType e;printf("双链表的基本运算如下:\n");printf("(1)初始化双链表 h\n");InitList(h);printf("(2)依次采用尾插法插入元素 a,b,c,d,e\n");ListInsert(h, 1, 'a');ListInsert(h, 2, 'b');ListInsert(h, 3, 'c');ListInsert(h, 4, 'd');ListInsert(h, 5, 'e');printf("(3)输出双链表 h:");DispList(h);printf("(4)双链表 h 长度:%d\n", ListLength(h));printf("(5)双链表 h 为%s\n", (ListEmpty(h) ? "空" : "非空"));GetElem(h, 3, e);printf("(6)双链表 h 的第 3 个元素:%c\n", e);printf("(7)元素 a 的位置:%d\n", LocateElem(h, 'a'));printf("(8)在第 4 个元素位置上插入元素 f\n");ListInsert(h, 4, 'f');printf("(9)输出双链表 h:");DispList(h);printf("(10)删除 h 的第 3 个元素\n");ListDelete(h, 3, e);printf("(11)输出双链表 h:");DispList(h);printf("(12)释放双链表 h\n");DestroyList(h);return 0;
}
代码结果与思路
-
创建链表函数
- 头插法创建双向链表(
CreateListF
):- 首先为头结点分配内存空间,并将头结点的前驱和后继指针都置为
NULL
。 - 然后遍历输入的数组,对于数组中的每个元素:
- 分配新节点
s
的内存空间。 - 将新节点
s
的数据域设置为当前数组元素的值。 - 将新节点
s
插入到头结点之后,具体操作是让新节点的next
指针指向原来头结点的下一个节点,如果原来头结点有下一个节点,则让原来头结点的下一个节点的前驱指针指向新节点;再让头结点的next
指针指向新节点,新节点的前驱指针指向头结点。
- 分配新节点
- 首先为头结点分配内存空间,并将头结点的前驱和后继指针都置为
- 尾插法创建双向链表(
CreateListR
):- 同样先为头结点分配内存空间,并初始化头结点的前驱和后继指针为
NULL
。 - 设置一个指针
r
指向头结点,作为尾指针。 - 遍历输入数组,对于每个元素:
- 分配新节点
s
的内存空间。 - 将新节点
s
的数据域设置为当前数组元素的值。 - 将新节点
s
插入到尾指针r
之后,即让尾指针r
的next
指针指向新节点,新节点的前驱指针指向尾指针r
;然后更新尾指针r
为新节点。
- 分配新节点
- 最后将尾指针的
next
指针置为NULL
,表示链表的末尾。
- 同样先为头结点分配内存空间,并初始化头结点的前驱和后继指针为
- 头插法创建双向链表(
-
初始化链表函数(
InitList
):为双向链表分配头结点空间,并将头结点的前驱和后继指针都置为NULL
,完成链表的初始化。 -
判断链表是否为空函数(
ListEmpty
):只需要检查头结点的next
指针是否为NULL
,如果是,则链表为空,返回true
;否则返回false
。 -
求链表长度函数(
ListLength
):- 从链表头结点开始遍历,设置一个指针
p
指向头结点,设置一个计数器i
初始值为 0。 - 当
p
的next
指针不为NULL
时,说明还有节点未遍历,计数器i
加一,移动指针p
指向下一个节点。 - 遍历结束后,返回计数器
i
的值,即为链表的长度。
- 从链表头结点开始遍历,设置一个指针
-
输出链表函数(
DispList
):从链表的第一个有效节点开始输出,设置一个指针p
指向头结点的下一个节点。当p
不为NULL
时,输出p
所指节点的数据域,然后移动指针p
指向下一个节点,继续输出直到链表末尾。 -
求链表中第 i 个元素的值函数(
GetElem
):- 首先检查输入的序号
i
是否合法(大于 0),如果不合法则返回false
。 - 设置一个指针
p
指向头结点,一个计数器j
初始值为 0。 - 当
j
小于i
且p
不为NULL
时,计数器j
加一,移动指针p
指向下一个节点。 - 如果遍历结束后
p
为NULL
,说明没有找到第i
个节点,返回false
;否则将p
所指节点的数据域赋值给参数e
,并返回true
。
- 首先检查输入的序号
-
查找第一个值域为 e 的元素的序号函数(
LocateElem
):- 从链表的第一个有效节点开始查找,设置一个计数器
i
初始值为 1,设置一个指针p
指向头结点的下一个节点。 - 当
p
不为NULL
且p
所指节点的数据域不等于要查找的值e
时,计数器i
加一,移动指针p
指向下一个节点。 - 如果遍历结束后
p
为NULL
,说明没有找到值为e
的节点,返回 0;否则返回计数器i
的值,即找到的节点的序号。
- 从链表的第一个有效节点开始查找,设置一个计数器
-
在链表中插入第 i 个元素函数(
ListInsert
):- 首先检查输入的序号
i
是否合法(大于 0),如果不合法则返回false
。 - 设置一个指针
p
指向头结点,一个计数器j
初始值为 0。 - 当
j
小于i - 1
且p
不为NULL
时,计数器j
加一,移动指针p
指向下一个节点,目的是找到要插入位置的前一个节点。 - 如果遍历结束后
p
为NULL
,说明没有找到要插入位置的前一个节点,返回false
。 - 分配新节点
s
的内存空间,设置新节点的数据域为要插入的值e
。 - 将新节点
s
插入到节点p
之后,具体操作是让新节点的next
指针指向p
的下一个节点,如果p
有下一个节点,则让p
的下一个节点的前驱指针指向新节点;再让新节点的前驱指针指向p
,p
的next
指针指向新节点。最后返回true
表示插入成功。
- 首先检查输入的序号
-
删除链表中第 i 个元素函数(
ListDelete
):- 首先检查输入的序号
i
是否合法(大于 0),如果不合法则返回false
。 - 设置一个指针
p
指向头结点,一个计数器j
初始值为 0。 - 当
j
小于i - 1
且p
不为NULL
时,计数器j
加一,移动指针p
指向下一个节点,目的是找到要删除节点的前一个节点。 - 如果遍历结束后
p
为NULL
,说明没有找到要删除节点的前一个节点,返回false
。 - 设置一个指针
q
指向p
的下一个节点,如果q
为NULL
,说明不存在第i
个节点,返回false
。 - 将
q
所指节点的数据域赋值给参数e
,然后将节点q
从链表中删除,具体操作是让p
的next
指针指向q
的下一个节点,如果q
的下一个节点存在,则让q
的下一个节点的前驱指针指向p
;最后释放节点q
的内存空间,并返回true
表示删除成功。
- 首先检查输入的序号
-
销毁链表函数(
DestroyList
):
- 从链表头结点开始,依次释放每个节点的内存空间。设置两个指针
pre
和p
,pre
初始指向头结点,p
初始指向头结点的下一个节点。 - 当
p
不为NULL
时,释放pre
所指节点的内存空间,然后将pre
指向p
,p
指向p
的下一个节点。 - 当
p
为NULL
时,说明链表中的所有节点都已释放,再释放pre
所指的头结点的内存空间。
实验题4:实现循环单链表的各种基本运算的算法
题目描述
编写一个程序clinklist.cpp,实现循环单链表的各种基本运算和整体建表算法
(假设循环单链表的元素类型ElemType为int),并在此基础上设计一个程序exp2-4.cpp
完成以下功能。
(1)初始化循环单链表h。
(2)依次采用尾插法插入元素a、b、c、d、e。
(3)输出循环单链表h。
(4)输出循环单链表h的长度。
(5)判断循环单链表h是否为空。
(6)输出循环单链表h的第3个元素。
(7)输出元素a的位置。
(8)在第4个元素的位置上插入元素f。
(9)输出循环单链表h。
(10)删除循环单链表h的第3个元素。
(11)输出循环单链表h。
(12)释放循环单链表h。
算法:clinklist.cpp程序,其中包含如下函数。
· InitList(LinkNode*&L):初始化循环单链表L。
· DestroyList(LinkNode*L):释放循环单链表L。
· ListEmpty(LinkNode *L):判断循环单链表L是否为空表。
· ListLength(LinkNode *L):返回循环单链表L中的元素个数。
· DispList(LinkNode *L):输出循环单链表L。
· GetElem(LinkNode *L,int i,ElemType &e):获取循环单链表L中的第i个元素。
· LocateElem(LinkNode*L,ElemType e):在循环单链表L中查找元素e。
· ListInsert(LinkNode*&L,int i,ElemType e):在循环单链表L中的第i个位置
上插入元素e。
· ListDelete(LinkNode*&L,int i,ElemType &e):从循环单链表L中删除第i个
元素。
运行代码
clinklist.cpp
#include <stdio.h>
#include <stdlib.h>typedef int ElemType;
typedef struct Node
{ElemType data;struct Node* next;
} LinkNode;// 头插法创建循环单链表
void CreateListF(LinkNode*& L, ElemType a[], int n)
{LinkNode* s;int i;// 分配头结点空间L = (LinkNode*)malloc(sizeof(LinkNode));L->next = NULL;for (i = 0; i < n; i++){// 分配新结点空间s = (LinkNode*)malloc(sizeof(LinkNode));s->data = a[i];// 将新结点插入头结点之后s->next = L->next;L->next = s;}// 找到尾结点,让尾结点的 next 指向头结点 L,形成循环链表s = L->next;while (s->next != NULL){s = s->next;}s->next = L;
}// 尾插法创建循环单链表
void CreateListR(LinkNode*& L, ElemType a[], int n)
{LinkNode* s, * r;int i;// 分配头结点空间L = (LinkNode*)malloc(sizeof(LinkNode));L->next = NULL;r = L;for (i = 0; i < n; i++){// 分配新结点空间s = (LinkNode*)malloc(sizeof(LinkNode));s->data = a[i];// 将新结点插入终端结点(r 指向的结点)之后r->next = s;r = s;}// 让尾结点的 next 指向头结点 L,形成循环链表r->next = L;
}// 初始化循环单链表
void InitList(LinkNode*& L)
{// 分配头结点空间L = (LinkNode*)malloc(sizeof(LinkNode));// 头结点的 next 指向自身,形成只有一个头结点的循环链表L->next = L;
}// 销毁循环单链表
void DestroyList(LinkNode*& L)
{LinkNode* pre = L, * p = pre->next;while (p != L){// 释放前一个结点free(pre);pre = p;// p 指向下一个结点p = p->next;}// 释放最后一个结点(此时 pre 指向最后一个结点)free(pre);
}// 判断循环单链表是否为空
bool ListEmpty(LinkNode* L)
{return L->next == L;
}// 求循环单链表的长度
int ListLength(LinkNode* L)
{LinkNode* p = L;int i = 0;while (p->next != L){// 移动到下一个结点p = p->next;// 长度加一i++;}return i;
}// 输出循环单链表
void DispList(LinkNode* L)
{LinkNode* p = L->next;while (p != L){// 输出当前结点的数据printf("%c ", p->data);// 移动到下一个结点p = p->next;}printf("\n");
}// 求循环单链表中第 i 个元素的值
bool GetElem(LinkNode* L, int i, ElemType& e)
{int j = 1;LinkNode* p = L->next;if (i <= 0 || L->next == L)return false;if (i == 1){// 提取第一个结点的值e = L->next->data;return true;}while (j <= i - 1 && p != L){// 移动到下一个结点j++;p = p->next;}if (p == L)return false;else{// 提取第 i 个结点的值e = p->data;return true;}
}// 查找第一个值域为 e 的元素的序号
int LocateElem(LinkNode* L, ElemType e)
{LinkNode* p = L->next;int i = 1;while (p != L && p->data != e){// 移动到下一个结点p = p->next;// 序号加一i++;}if (p == L)return 0;elsereturn i;
}// 在循环单链表中插入第 i 个元素
bool ListInsert(LinkNode*& L, int i, ElemType e)
{int j = 1;if (i <= 0) return false;if (L->next == L || i == 1){LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = e;s->next = L->next;L->next = s;return true;}LinkNode* p = L->next;while (j <= i - 2 && p != L){j++;p = p->next;}if (p == L)return false;else{LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = e;s->next = p->next;p->next = s;return true;}
}// 删除循环单链表中第 i 个元素
bool ListDelete(LinkNode*& L, int i, ElemType& e)
{int j = 1;LinkNode* p = L, * q;if (i <= 0 || L->next == L)return false;if (i == 1){q = L->next;e = q->data;L->next = q->next;free(q);return true;}while (j < i - 1 && p != L){j++;p = p->next;}if (p == L)return false;else{q = p->next;e = q->data;p->next = q->next;free(q);return true;}
}
Excp2-4.cpp
#include <stdio.h>
#include <stdlib.h>
#include "clinklist.cpp"int main() {LinkNode* h;ElemType e;printf("循环单链表的基本运算如下:\n");printf("(1)初始化循环单链表 h\n");InitList(h);printf("(2)依次采用尾插法插入元素 a,b,c,d,e\n");ListInsert(h, 1, 'a');ListInsert(h, 2, 'b');ListInsert(h, 3, 'c');ListInsert(h, 4, 'd');ListInsert(h, 5, 'e');printf("(3)输出循环单链表 h:");DispList(h);printf("(4)循环单链表 h 长度:%d\n", ListLength(h));printf("(5)循环单链表 h 为%s\n", (ListEmpty(h) ? "空" : "非空"));GetElem(h, 3, e);printf("(6)循环单链表 h 的第 3 个元素:%c\n", e);printf("(7)元素 a 的位置:%d\n", LocateElem(h, 'a'));printf("(8)在第 4 个元素位置上插入元素 f\n");ListInsert(h, 4, 'f');printf("(9)输出循环单链表 h:");DispList(h);printf("(10)删除 h 的第 3 个元素\n");ListDelete(h, 3, e);printf("(11)输出循环单链表 h:");DispList(h);printf("(12)释放循环单链表 h\n");DestroyList(h);return 0;
}
代码结果与思路
定义了一个循环单链表的节点结构体Node
(重命名为LinkNode
),包含以下成员:
data
:存储节点的数据,这里数据类型为ElemType
,实际上是int
类型。next
:指向下一个节点的指针。
-
创建链表函数
- 头插法创建循环单链表(
CreateListF
):- 首先为头结点分配内存空间,并将头结点的
next
指针置为NULL
。 - 然后遍历输入的数组,对于数组中的每个元素:
- 分配新节点
s
的内存空间。 - 将新节点
s
的数据域设置为当前数组元素的值。 - 将新节点
s
插入到头结点之后,具体操作是让新节点的next
指针指向原来头结点的下一个节点,再让头结点的next
指针指向新节点。
- 分配新节点
- 最后找到尾结点,让尾结点的
next
指针指向头结点,形成循环链表。
- 首先为头结点分配内存空间,并将头结点的
- 尾插法创建循环单链表(
CreateListR
):- 同样先为头结点分配内存空间,并将头结点的
next
指针置为NULL
。 - 设置一个指针
r
指向头结点,作为尾指针。 - 遍历输入数组,对于每个元素:
- 分配新节点
s
的内存空间。 - 将新节点
s
的数据域设置为当前数组元素的值。 - 将新节点
s
插入到尾指针r
之后,即让尾指针r
的next
指针指向新节点,然后更新尾指针r
为新节点。
- 分配新节点
- 最后将尾指针的
next
指针指向头结点,形成循环链表。
- 同样先为头结点分配内存空间,并将头结点的
- 头插法创建循环单链表(
-
初始化链表函数(
InitList
):为循环单链表分配头结点空间,并将头结点的next
指针指向自身,形成只有一个头结点的循环链表。 -
销毁链表函数(
DestroyList
):- 从链表的第一个有效节点开始,依次释放每个节点的内存空间。设置两个指针
pre
和p
,pre
初始指向头结点,p
初始指向头结点的下一个节点。 - 当
p
不等于头结点时,释放pre
所指节点的内存空间,然后将pre
指向p
,p
指向p
的下一个节点。 - 当
p
等于头结点时,说明链表中的所有节点都已释放,再释放pre
所指的头结点的内存空间。
- 从链表的第一个有效节点开始,依次释放每个节点的内存空间。设置两个指针
-
判断链表是否为空函数(
ListEmpty
):只需要检查头结点的next
指针是否指向自身,如果是,则链表为空,返回true
;否则返回false
。 -
求链表长度函数(
ListLength
):- 从链表的第一个有效节点开始遍历,设置一个指针
p
指向头结点的下一个节点,设置一个计数器i
初始值为 0。 - 当
p
的next
指针不等于头结点时,说明还有节点未遍历,计数器i
加一,移动指针p
指向下一个节点。 - 遍历结束后,返回计数器
i
的值,即为链表的长度。
- 从链表的第一个有效节点开始遍历,设置一个指针
-
输出链表函数(
DispList
):- 从链表的第一个有效节点开始输出,设置一个指针
p
指向头结点的下一个节点。 - 当
p
不等于头结点时,输出p
所指节点的数据域,然后移动指针p
指向下一个节点,继续输出直到回到头结点。
- 从链表的第一个有效节点开始输出,设置一个指针
-
求链表中第 i 个元素的值函数(
GetElem
):- 首先检查输入的序号
i
是否合法(大于 0)以及链表是否为空,如果不合法或链表为空则返回false
。 - 如果
i
等于 1,直接提取头结点的下一个节点的值并返回true
。 - 如果
i
大于 1,设置一个指针p
指向头结点的下一个节点,一个计数器j
初始值为 1。 - 当
j
小于i - 1
且p
不等于头结点时,计数器j
加一,移动指针p
指向下一个节点,目的是找到第i
个节点的前一个节点。 - 如果遍历结束后
p
等于头结点,说明没有找到第i
个节点,返回false
;否则将p
的下一个节点的数据域赋值给参数e
,并返回true
。
- 首先检查输入的序号
-
查找第一个值域为 e 的元素的序号函数(
LocateElem
):- 从链表的第一个有效节点开始查找,设置一个计数器
i
初始值为 1,设置一个指针p
指向头结点的下一个节点。 - 当
p
不等于头结点且p
所指节点的数据域不等于要查找的值e
时,计数器i
加一,移动指针p
指向下一个节点。 - 如果遍历结束后
p
等于头结点,说明没有找到值为e
的节点,返回 0;否则返回计数器i
的值,即找到的节点的序号。
- 从链表的第一个有效节点开始查找,设置一个计数器
-
在链表中插入第 i 个元素函数(
ListInsert
):- 首先检查输入的序号
i
是否合法(大于 0),如果不合法则返回false
。 - 如果链表为空或者
i
等于 1,直接在头结点之后插入新节点,具体操作是分配新节点s
的内存空间,设置新节点的数据域为要插入的值e
,让新节点的next
指针指向头结点的下一个节点,再让头结点的next
指针指向新节点,最后返回true
表示插入成功。 - 如果
i
大于 1,设置一个指针p
指向头结点的下一个节点,一个计数器j
初始值为 1。 - 当
j
小于i - 2
且p
不等于头结点时,计数器j
加一,移动指针p
指向下一个节点,目的是找到要插入位置的前一个节点。 - 如果遍历结束后
p
等于头结点,说明没有找到要插入位置的前一个节点,返回false
。 - 分配新节点
s
的内存空间,设置新节点的数据域为要插入的值e
。 - 将新节点
s
插入到节点p
之后,具体操作是让新节点的next
指针指向p
的下一个节点,再让p
的next
指针指向新节点,最后返回true
表示插入成功。
- 首先检查输入的序号
-
删除链表中第 i 个元素函数(
ListDelete
):
- 首先检查输入的序号
i
是否合法(大于 0)以及链表是否为空,如果不合法或链表为空则返回false
。 - 如果
i
等于 1,直接删除头结点的下一个节点,具体操作是设置一个指针q
指向头结点的下一个节点,将q
所指节点的数据域赋值给参数e
,让头结点的next
指针指向q
的下一个节点,释放q
所指节点的内存空间,最后返回true
表示删除成功。 - 如果
i
大于 1,设置一个指针p
指向头结点,一个计数器j
初始值为 1。 - 当
j
小于i - 1
且p
不等于头结点时,计数器j
加一,移动指针p
指向下一个节点,目的是找到要删除节点的前一个节点。 - 如果遍历结束后
p
等于头结点,说明没有找到要删除节点的前一个节点,返回false
。 - 设置一个指针
q
指向p
的下一个节点,将q
所指节点的数据域赋值给参数e
,让p
的next
指针指向q
的下一个节点,释放q
所指节点的内存空间,最后返回true
表示删除成功。