将单循环链表改为双循环链表,单链表改为双向循环链表
伊德斯干货盘点
@TOC
一~我爱你~双向带头循环链表
二~我爱你~双向带头循环链表的实现
1.函数的定义和结构体的创建——名单h
#包括标准视频
#包括标准库
#include assert.h包含断言
typedef int数据类型
结构列表节点(结构列表节点)
数据类型val
结构列表节点*预测:
结构列表节点*下一个
struct list node * stack init();
void堆栈推回(struct listnode * phead,数据类型x);
void stack print(struct listnode * phead);
void堆栈弹出返回(struct listnode * phead);
void stack push Fran(struct listnode * phead,数据类型x);
void堆栈弹出前端(struct listnode * phead);
struct listnode * stack find(struct listnode * phead,数据类型x);
void堆栈插入(struct listnode * pos,数据类型x);
void stack destroy(struct listnode * phead);
2.函数的调用前334年
#包括list.h
int main()
struct listnode * phead=stack init();//这里为了不使用二级指针,将结构体指针返回
stackpushback(phead,1);
堆栈推回(phead,2);
堆栈推回(phead,3);
stackpushback(phead,4);
堆栈弹出返回(phead);
堆栈pushfran(phead,5);
堆栈弹出前端(phead);
堆栈打印(phead);
struct listnode * pos=stack find(phead,2);
斯塔金塞特(4号位);
堆栈打印(phead);
struct listnode * pos 2=堆栈查找(phead,2);
stackerase(pos2):
堆栈打印(phead);
栈式驱逐舰(phead);
phead=null
返回0;
}
3.双向带头循环链表与单链表的传递参数区别
1.单链表:
单链表因为没有头节点的存在,导致在尾插时会改变链表的头节点
所以需要传递二级指针的地址即二级指针。
2.双向带头循环链表:
初始化头指针时,是需要传递二级指针,只不过用函数传回结构体指针的方式代替了,
而在后续接口则不需要传递二级指针,因为后来都是在头指针的基础上进行的,而头节点本身不会存储有效数据,并不会改变头节点本身。
4.双向带头循环链表的接口
1.初始化
struct listNode* stackinit()//初始化头节点
struct listnode * phead=(struct listnode *)malloc(sizeof(struct listnode));
ph head-next=ph head;//带哨兵位的头节点
ph EAD-prev=ph EAD;
}
空堆栈回推(struct listnode * phead,数据类型x)/(s)尾插
struct listNode* tail=phead- prev(结构列表节点*尾部=phead-预测)://尾部为最后一个节点
struct listnode * new node=(struct listnode *)malloc(sizeof(struct listnode));
newnode- val=x:
尾部-下一个=新节点:
newnode- prev=tail(新节点-预测=尾部):
new node-next=phead;
phead-prev=新节点;
}
void堆栈弹出返回(struct listnode * phead)//尾删
断言(phead);
断言(phead-下一个!=phead//当只剩下头节点时phead-下一个才会指向菲德
struct listNode* tail=phead- prev(结构列表节点*尾部=phead-预测):
结构列表节点* cur=尾部-预测://rur为最后一个节点的前一个节点
cur-next=phd;
phead-prev=cur;
自由(尾部);
尾部=空:
}
空堆栈pushfran(struct listnode * phead,数据类型x/)头插
struct listnode * new node=(struct listnode *)malloc(sizeof(struct listnode));
newnode- val=x:
struct list node * cur=phead-next;
phead-next=新节点;
new node-prev=phead;
new node-next=cur;
cur-prev=新节点;
}
void堆栈弹出前端(struct listnode * phead)//头删
断言(phead);
断言(phead-下一个!=phead//链表为空时
struct list node * prev=phead-next;
结构列表节点* next=phead-next-下一个;//找到第一个节点后的一个节点
phead- next=下一个;
下一步-预测=phead
自由(上一页):
prev=NULL:
}
6.查找位置
结构列表节点*堆栈查找(结构列表节点* phead,数据类型x)//查找位置
struct list node * cur=phead-next;
而(当前值!=phead)
if (cur- val==x)
返回当前值;//如果找到了返回结构体
cur=cur-next;
返回NULL://如果找不到就返回空值
}
7.指定在位置(p)之前插入
请参见stackinsert(结构列表节点*位置,数据类型x)//指定插在位置(p)之前插入
断言(pos);
struct listNode* prev=pos- prev:
struct listnode * new node=(struct listnode *)malloc(sizeof(struct listnode));
newnode- val=x:
prev- next=newnode:
newnode- prev=prev:
newnode- next=pos:
pos-prev=新节点;
}
8.指定删除
void stack erase(struct listnode * pos)//指定删除
断言(位置);
struct list node * prev=pos-prev;
struct list node * next=pos-next;
prev-next=next;
next-prev=prev;
免费(pos);
pos=NULL
}
9.记忆破坏
void stack destroy(structlistnode * phead)//内存销毁
struct listNode * cur=phead-next;
而(cur!=phead)
struct list node * next=cur-next;
免费(cur);
cur=next
免费(phead);
phead=NULL//因为此时传递的一级指针不能影响将要传递回来的phead,所以可以在外面手动设置NULL。
10.打印
Void堆栈打印(struct listnode * phead)//打印
struct listNode * cur=phead-next;
而(cur!=phead)//此时因为是循环链表,所以不要写成NULL。
printf(%d ,cur-val);
cur=cur-next;
printf( \ n );
三、链表和顺序表的区别
1.序列表:
是物理上连续的。
优点:支持随机访问。
缺点:(1)在任意位置插入或删除时,可能需要移动元素,效率低。
(2)动态开辟空间时,会造成一定的浪费。
2.链接列表:
逻辑上的连续性,物理上的不连续性。
优点:(1)在任意位置插入或删除都不会移动元素,只会改变指针指向;(2)没有容量的概念,不会造成空间浪费。
缺点:不支持随机访问。
。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。