线性表--顺序表--双向链表(六)
时间:2022-07-28
本文章向大家介绍线性表--顺序表--双向链表(六),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
双向链表图示
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
1.定义链表
typedef struct Node
{
int data;
struct Node * prior;
struct Node * next;
}Node;
2.初始化头尾结点
Node * InitListHead()
{
Node * Head = (Node *)malloc(sizeof(Node));
Head->data = 0;
Head->next = NULL;
Head->prior = NULL;
return Head;
}
Node * InitListEnd()
{
Node * End = (Node *)malloc(sizeof(Node));
End->data = 0;
End->next = NULL;
End->prior = NULL;
return End;
}
3.初始化链表结点
void CreateCLinkList(Node ** Head,Node ** End,int a)//创建节点
{
//尾插法
Node * P = (Node *)malloc(sizeof(Node));
P->data = a;
if ((*Head)->next == NULL)
{
(*Head)->next = P;
P->prior = (*Head);
}
else
{
(*End)->prior->next = P;
P->prior = (*End)->prior;
}
P->next = (*End);
(*End)->prior = P;
(*Head)->data++;
}
4.插入操作
(1)图示
(2)代码
int InsertList(Node ** Head, Node ** End,int i,int num)//i为插入位置
{
//我们可以在头结点的数据存储链表长度,来判断插入位置是否合法,这里假定输入的i合法
//因为有首尾链表,我们可还以判断输入位置在前半部分,还是后半部分,从而选择使用头节点还是尾节点,这里就不做示范了
j = 0;
Node *Phead = (*Head);
Node *Pend = (*End);
Node * P = (Node *)malloc(sizeof(Node));
P->data = num;
if (i > (*Head)->data)
return 0;
//正向操作
//while (Phead != NULL)
//{
// if (i == j+1)
// {
// Phead->next->prior = P;
// P->next = Phead->next;
// Phead->next = P;
// P->prior = Phead;
// (*Head)->data++;
// }
// Phead = Phead->next;
// j++;
//}
//这不是我们今天的重点 今天的重点是 双向链表的逆向操作:
while (Pend->prior != NULL)
{
if (Phead->data - i == j)
{
P->prior = Pend->prior;
Pend->prior->next = P;
P->next = Pend;
Pend->prior = P;
(*Head)->data++;
return 0;
}
Pend = Pend->prior;
j++;
}
return 0;
}
5.遍历操作
void printList(Node * Head, Node * End)
{
//双向链表的遍历条件是头指针是否等于尾节点,或者是指针是否为空
Node * Phead = Head->next;
Node * Pend = End->prior;
//正向操作
//while (Phead->next != NULL)
//{
// printf("第一种 %dn", Phead->data);
// Phead = Phead->next;
//}
//printf("n");
//Node * Phead_1 = Head->next;
//while (Phead_1 != Pend)
//{
// printf("第二种 %dn", Phead_1->data);
// Phead_1 = Phead_1->next;
//}
//同样这也是正向操作,下面来看逆向操作
while (Pend->prior != NULL)
{
printf("第一种 %dn", Pend->data);
Pend = Pend->prior;
}
printf("n");
}
6.删除操作
int DelList(Node ** Head, Node ** End, int i)
{
j = 0;
Node *Phead = (*Head);
Node *Pend = (*End);
Node * P = NULL;
if (i > (*Head)->data)
return 0;
//正向操作
//while (Phead->next != NULL)
//{
// if (i == j + 1)
// {
// P = Phead->next;
// Phead->next = Phead->next->next;
// Phead->next->prior = Phead;
// P->next = NULL;
// P->prior = NULL;
// free(P);
// (*Head)->data--;
// }
// Phead = Phead->next;
// j++;
//}
//同样,我们来看逆向操作:
while (Pend->prior != NULL)
{
if (Phead->data - i == j+1 )
{
P = Pend->prior;
Pend->prior->next = Pend;
Pend->prior = Pend->prior->prior;
P->next = NULL;
P->prior = NULL;
free(P);
(*Head)->data--;
}
Pend = Pend->prior;
j++;
}
return 0;
}
7.int main()操作
int main()
{
int j=0;
Node * Head = InitListHead();
Node * End = InitListEnd();
Node ** PH = &Head;
Node ** PE = &End;
for (int i = 1; i <= 10; i++)
{
CreateCLinkList(PH, PE, i);
}
printList(Head, End);
InsertList(PH, PE, 3, 99);
printList(Head, End);
DelList(PH, PE, 3);
printList(Head, End);
return 0;
}
8.切记申请的内存记得要释放哦!!!
若有错误。欢迎批评指出,欢迎交流。 每文一句:生命中,不断地有人离开或进入。于是,看见的,看不见了;记住的,以往了。生命中,不断地有得到或失落。于是看不见的,看见了;以往的,记住了,然而,看不见的,是不是就等于不存在?记住的,永远不会消失?
- ADO.NET入门教程(七) 谈谈Command对象高级应用
- ADO.NET入门教程(八) 深入理解DataAdapter(上)
- 深入理解DIP、IoC、DI以及IoC容器
- C#委托使用详解(Delegates)
- LINC switch系列之安装指南
- 设计模式成长记(一) 抽象工厂模式(Abstract Factory)
- 基于Open vSwitch的VxLAN隧道实验网络
- 来来来,快来围观那个Kotlin
- 怎样提高网站访问速度缩短网页加载时间
- 使用Kotlin开发一个Spring Boot Webflux Streaming应用(附视频)
- 插入排序算法
- Javascript 的addEventListener()及attachEvent()区别分析
- 设计模式-用接口来实现filter!梭梭就是干!
- OpenDaylight实现轮询策略的负载均衡服务
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- TCP的三次握手和四次挥手
- Springboot异常处理
- Excel实战技巧84: 让形状生动起来
- 利用Python进行组合数计算
- Docker下解决mysql出现"the table is full"的问题
- unity3d 5.0中Renderer后面没有了material
- 在windows下检查应用程序是否为兼容模式启动及使用Qt输出系统信息
- Qt5.5.1版本中QString().arg()和qss在处理路径及文件名需要注意的地方
- Typecho将Gravatar头像改为QQ头像
- python socket 简单示例
- 深入了解C++虚函数
- Mathematica 在高考数学与高等数学等学习中的简单应用与思考
- 数据结构之【实现数组】
- 数据结构【单链表基本操作】
- Django Models 随机获取指定数量数据方法