数据结构_day07_09-06
1、线性表
1. 循环链表
循环链表:头尾相连的链表,即尾结点的指针域指向头结点
循环终止条件:指针p的指针域不指向头结点
注:由于操作链表时会经常操作首尾结点,而查询尾结点需要进行遍历,较不方便,故可用尾指针表示单循环链表
首元结点:R->next->next
尾结点:R
例:带尾指针循环链表的合并
- Ta的尾结点指针域指向Tb的首元结点
- 释放Tb的头结点
- Tb的尾结点指针域指向Ta的头结点
Node* p = Ta->next;
Ta->next = Tb->next->next;
free(Tb->next);
Tb->next = p;
2. 双向链表
双向链表:链表的结点同时保存结点的前趋和后继(其中头结点的前趋结点为NULL,尾结点的后继结点为NULL)
双向链表的存储:
typedef struct DulNode
{
Data data;
struct Node* prior;
struct Node* next;
}DulNode, * DulLinkList;
双向链表的特点:
- 对称性:结点p的前趋的后继 = 节点p = 结点p的后继的前趋
双向链表的操作:
- InsertList(&L, i, e)
Status InsertList(DulLinkList list, int i, Data* data)
{
DulNode* p = list;
int count = 0;
// 查找结点
while (p && count < i - 1)
{
p = p->next;
count++;
}
if (!p || count > i - 1)
{
return ERROR;
}
else
{
// 新建结点
DulNode* node = (DulNode*)malloc(sizeof(DulNode));
if (node)
{
memcpy(&(node->data), data, sizeof(Data));
node->next = p->next;
p->next->prior = node;
node->prior = p;
p->next = node;
return OK;
}
else
{
return OVERFLOW;
}
}
}
注:上述方法无法插入空表
- DeleteList(&L, i)
// 类似于单链表,故具体步骤省略
p->prior->next = p->next;
p->next->prior = p->prior;