文章目录
一、双向链表存储结构
1、了解
对于单链表来说,不能回退,只能顺序进行,所以就有了双向链表
2、定义
双向链表中每个数据结点除了存储自身数据元素信息外,还有两个指针,分别指向直接后继和直接前驱。
这样我们就可以从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
3、结构
前驱指针(prev):指向该结点的上一个元素,最后一个指针域为空
后继指针(next):指向该结点的下一个元素,最后一个指针域为空
数据域(data):存放每个结点的数据
二、双链表的结构设计
typedef int ElemType;//重定义一个新的数据类型
typedef struct Node
{
ElemType data;
struct Node* prev;
struct Node* next;
}Node, *DPList;
三、初始化
创建双链表
判空的原因:当main函数中,如果出现head(NULL);时会导致指向了一个无效的地址,所以要先判断指向地址的节点是否合理
void init(DPList plist)
{
if (plist == NULL)
{
exit(0);
}
plist->data = 0;
plist->prev = NULL;
plist->next = NULL;
}
与单链表不同的是,双向链表要对前驱结点进行初始化。
四、插入操作
- 插入操作分为头插、尾插、按位置插入
- 函数整体用的是int类型原因:
如果是void类型,如果是非法位置,则无法插入元素,所以要用int类型,返回值用来接收插入的状态,看是否插入成功 - 插入操作主要是生成一个新的结点用来插入
1、开辟新结点pnewnode
Node* buyNode(ElemType val)
{
Node* pnewnode = (Node*)malloc(sizeof(Node));
pnewnode->prev = pnewnode->next = NULL;
pnewnode->data = val;
return pnewnode;
}
2、分析
进行插入操作时,要进行以下四步
Node* pfront = plist;
plist->next = pnewnode;//1
pnewnode->next = plist->next;//2
pfront->next->prev = pnewnode;