来自AI助手的总结
双向循环链表通过头插法、尾插法等实现节点的增删查改,并提供初始化、销毁及统计功能。
双向循环链表的基本结构:
一个数据域,一个指向下一个节点的next指针域,指向前一个节点的prior指针域。
typedef struct DulNode{
ElemType data;
struct DulNode *prior;
struct DulNode *next;
}DulNode, *DulLinkList;
对于ElemType,,以及用于比较的函数,我们假定有
typedef struct stu{
char name[50];
char id[50];
}stu;
typedef stu ElemType;
bool cmp(ElemType e1, ElemType e2)
{
if(strcmp(e1.name, e2.name) == 0 && strcmp(e1.id, e2.id) == 0)
return true;
return false;
}
初始化:
- 对头节点进行内存分配。分配失败返回NULL.
- 将前驱指针和后继指针指向头节点。
- 返回头节点的地址。
DulNode *InitList (DulLinkList L)
{
L = (DulNode *)malloc(sizeof(DulNode));
if(L == NULL)
return NULL;
L->next = L;
L->prior = L;
return L;
}
头插法:
- 对一个节点进行内存分配,如果分配内存失败返回NULL。
- 将数据存储进入数据域。
- 将新节点的next指针指向头节点的next指针指向的地址。
- 将头节点的next指针指向的节点的前驱节点指针指向新节点的地址。
- 将新节点的前驱节点指针指向新节点。
- 将新节点的后继节点指针指向新节点。
- 返回新节点的地址。
实现代码如下:
DulNode *Insert_Head(DulLinkList L, ElemType e) //头插法
{
DulLinkList p = (DulNode *)malloc(sizeof(DulNode));
if(p == NULL)
return NULL;
p->data = e; //将数据储存进数据域
p->next = L->next; //将新结点的后继结点指针指向前驱结点的后继指针指向的地址(头结点)
L->next->prior = p;
p->prior = L;
L->next = p; //将头结点的后继指针指向新结点
return p;
}
双向循环链表数据的插入(尾插法)
尾插法是将新节点插入到链表尾部的操作。设计思路如下:
- 创建一个新节点,并填充数据。
- 找到链表的最后一个节点。
- 将新节点的前驱指针指向最后一个节点。
- 将新节点的后继指针指向头结点。
- 更新最后一个节点的后继指针指向新节点。
- 更新头结点的前驱指针指向新节点。
实现代码如下:
DulNode *Insert_Tail(DulLinkList L, ElemType e) {
DulNode *p = (DulNode *)malloc(sizeof(DulNode));
if (p == NULL)
return NULL;
p->data = e; // 将数据储存进数据域
DulNode *tail = L->prior; // 找到最后一个节点
p->next = L; // 新节点的后继指针指向头结点
p->prior = tail; // 新节点的前驱指针指向最后一个节点
tail->next = p; // 最后一个节点的后继指针指向新节点
L->prior = p; // 更新头结点的前驱指针
return p;
}
在指定位置插入元素
在指定位置插入元素的设计思路如下:
- 检查插入位置是否合法。
- 为新节点分配内存并验证。
- 找到待插入位置的前一个节点。
- 更新指针来完成插入操作。
实现代码如下(假设位置从头结点开始计数):
bool InsertAtPosition(DulLinkList L, int pos, ElemType e) {
if (pos < 1) // 检查位置是否合法
return false;
DulNode *p = L;
for (int i = 1; i < pos && p->next != L; i++) // 遍历到插入位置
p = p->next;
DulNode *newNode = (DulNode *)malloc(sizeof(DulNode));
if (newNode == NULL) // 检查内存分配
return false;
newNode->data = e;
// 插入操作
newNode->prior = p;
newNode->next = p->next;
p->next->prior = newNode;
p->next = newNode;
return true;
}
删除某个位置的节点
删除指定位置的节点的设计思路如下:
- 检查链表是否为空或位置是否合法。
- 找到要删除节点的前一个节点。
- 调整指针以删除节点。
- 释放内存。
实现代码如下:
DulNode *DeleteAtPosition(DulLinkList L, int pos) {
if (pos < 1 || L->next == L) // 注意链表是否为空
return NULL;
DulNode *p = L;
for (int i = 1; i < pos && p->next != L; i++) // 遍历到删除位置
p = p->next;
DulNode *q = p->next; // q 为待删除节点
if (q == L) // 如果 q 等于头结点
return NULL;
// 调整指针
p->next = q->next;
q->next->prior = p;
return q; // 返回被删除节点
}
删除链表中的某个值
删除链表中某个值的设计思路如下:
- 创建两个指针,一个指向当前节点,另一个指向前驱节点。
- 遍历链表,找到匹配的值并进行删除。
- 更新指针以保持链表的结构完整。
实现代码如下:
void DeleteValue(DulLinkList L, ElemType value) {
DulNode *p = L->next; // 从头结点的后继开始
while (p != L) {
if (p->data == value) {
// 调整前驱节点和后继节点的指针
p->prior->next = p->next;
p->next->prior = p->prior;
DulNode *temp = p;
p = p->next; // 继续遍历
free(temp); // 释放内存
} else {
p = p->next; // 继续遍历
}
}
}
销毁整个链表
销毁整个链表的步骤如下:
- 使用一个指针遍历整个链表。
- 在遍历过程中,逐个释放节点的内存。
实现代码如下:
void DestroyDulList(DulLinkList L) {
DulNode *p = L->next; // 从头结点的后继开始
while (p != L) {
DulNode *temp = p;
p = p->next; // 保存下一个节点
free(temp); // 释放当前节点
}
free(L); // 最后释放头节点
}
查询某个值是否存在
查询某个值是否存在的步骤如下:
- 从头结点的后继节点开始遍历。
- 如果找到匹配的值,则返回true。
- 到达头结点时未找到则返回false。
实现代码如下:
bool FindValue(DulLinkList L, ElemType e) {
DulNode *p = L->next; // 从头结点的后继开始
while (p != L) {
if (p->data == e)
return true; // 如果找到就返回true
p = p->next; // 否则继续遍历
}
return false; // 如果遍历完未找到,返回false
}
统计链表中的节点数量
统计链表中的节点数量的步骤如下:
- 使用一个计数器遍历整个链表。
- 每遍历一个节点就加一。
实现代码如下:
int Size(DulLinkList L) {
int count = 0;
DulNode *p = L->next; // 从头结点的后继开始
while (p != L) {
count++;
p = p->next; // 遍历下一个节点
}
return count;
}
查询链表是否为空
如果头结点的后继指针指向自身,则说明链表为空,返回true;否则返回false。
实现代码如下:
bool IsEmpty(DulLinkList L) {
return L->next == L; // 判断头结点的后继是否指向自身
}
修改某个节点的数据域
修改某个节点的数据域的步骤如下:
- 检查位置是否合法。
- 找到待修改的节点。
- 修改数据域。
实现代码如下:
bool ChangeValue(DulLinkList L, int pos, ElemType e) {
if (pos < 1 || pos > Size(L) || IsEmpty(L))
return false;
DulNode *p = L->next;
for (int i = 1; i < pos; i++)
p = p->next; // 遍历到指定位置
p->data = e; // 修改数据域
return true;
}
总的实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int ElemType;
typedef struct DulNode {
ElemType data;
struct DulNode *next;
struct DulNode *prior;
} DulNode, *DulLinkList;
DulLinkList InitDulList();
DulNode *Insert_Head(DulLinkList L, ElemType e);
DulNode *Insert_Tail(DulLinkList L, ElemType e);
bool InsertAtPosition(DulLinkList L, int pos, ElemType e);
DulNode *DeleteAtPosition(DulLinkList L, int pos);
void DeleteValue(DulLinkList L, ElemType value);
void DestroyDulList(DulLinkList L);
bool FindValue(DulLinkList L, ElemType e);
int Size(DulLinkList L);
bool IsEmpty(DulLinkList L);
bool ChangeValue(DulLinkList L, int pos, ElemType e);
int main() {
DulLinkList L = InitDulList();
// 进行相关操作测试
return 0;
}
没有回复内容