数据结构_day07_09-06

1、线性表

1. 循环链表

循环链表:头尾相连的链表,即尾结点的指针域指向头结点

循环终止条件:指针p的指针域不指向头结点

注:由于操作链表时会经常操作首尾结点,而查询尾结点需要进行遍历,较不方便,故可用尾指针表示单循环链表

首元结点:R->next->next

尾结点:R

例:带尾指针循环链表的合并

  1. Ta的尾结点指针域指向Tb的首元结点
  2. 释放Tb的头结点
  3. 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;