王道数据结构双链表实现头插法、删除、前向遍历、后向遍历、销毁操作
源码:
#include <stdio.h>
#include <stdlib.h>
typedef struct DNode {
int data;
struct DNode* prior, * next;
}DNode,*DLinkList;
bool InitDLinkList(DLinkList& L) {
L = (DNode*)malloc(sizeof(DNode));
if (L == NULL)
return false;
L->prior = NULL; //piror永远指向null
L->next = NULL;
return true;
}
//在p结点之后插入s结点
bool InsertNextDNode(DNode* p, DNode* s) {
if (p == NULL || s == NULL) //防止p结点是最后一个时产生的空指针异常
{
printf("非法参数1!\n");
return false;
}
s->next = p->next;
if (p->next != NULL)//如果p结点有后继结点才可以修改p的后继结点的前向指针
p->next->prior = s;
s->prior = p;
p->next = s;
return true;
}
//删除p结点的后继结点
bool DeleteNextDNode(DNode* p) {
if (p == NULL)
{
printf("非法参数2!\n");
return false;
}
DNode* q = p->next;//找到p的后继结点q
if (q == NULL)//p没有后继
{
printf("非法参数3!\n");
return false;
}
p->next = q->next;
if (q->next != NULL)
q->next->prior = p;
free(q);
return true;
}
bool Empty(DLinkList L) {
if (L->next == NULL) {
printf("表空.\n");
printf("=======================\n");
return true;
}
else {
printf("=======================\n");
printf("表创建成功.\n");
printf("=======================\n");
return false;
}
}
void testDLinkList(DLinkList L) {
DNode* p;
DNode* s;
int data;
printf("输入数据,999退出:\n");
scanf_s("%d", &data);
while (data != 999) {
s = (DNode*)malloc(sizeof(DNode));
s->data = data;
InsertNextDNode(L, s);//封装操作
scanf_s("%d", &data);
}
if (Empty(L))
return;
printf("前向遍历,p->prior得到的双链表如下:\n");
p = L->next;
while (p->next != NULL)//循环使得p结点指向表尾
{
p = p->next;
}
while (p != NULL && p != L)
{
printf("%d ", p->data);
p = p->prior;//前向遍历,p->prior;向后遍历p->next
}
printf("\n");
//删除第一个结点的后继结点并后向遍历打印
p = L->next;
DNode* t = L->next;
DeleteNextDNode(t);
printf("删除第一个结点的后继结点并后向遍历打印:\n");
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
}
//销毁双链表 (慎用)
void DestoryDList(DLinkList& L) {
while (L->next != NULL)
DeleteNextDNode(L);
free(L);
L = NULL;//头指针指向null
printf("\n=======================\n");
printf("已销毁双链表");
}
int main() {
DLinkList L;
InitDLinkList(L);
testDLinkList(L);
DestoryDList(L);
return 0;
}
运行截图:
直接输入999,表空:
正常输入一些数据:
感想、总结
因为双链表的操作和单链表是大致相同的,所以我的代码写的比较潦草,仅仅把基本的功能实现了,代码可以优化简洁处理,也可以添加按位序查找、前置结点插入等操作。
void函数是默认返回值的,想跳出void直接return;
就可以了。
附上一些草图,挺好玩的🤣
循环完以后是这样
后面的小朋友走丢了,没有指针指向队尾。
这个时候把p指针循环一下,让他指向队尾好了:
p = L->next;
while (p->next != NULL)//循环使得p结点指向表尾
{
p = p->next;
}
附一张王道数据结构学习的知识清单图: