1. 程式人生 > >雙鏈表(雙向帶頭迴圈連結串列)

雙鏈表(雙向帶頭迴圈連結串列)

雙向連結串列

雙向連結串列也叫雙鏈表,是連結串列中的一種。它的每個資料結點中都有兩個指標,分別指向直接前驅和直接後繼,所以從連結串列的任意一個結點都可以很方便的訪問到它的前驅結點和後繼結點,一般我們都構造雙向迴圈連結串列。
## 帶頭結點和不帶頭結點   其實這個帶頭結點和不帶頭結點在單鏈表那篇部落格中就應該提的,但是我放在這裡,原因是,本篇主要介紹帶頭結點的雙向迴圈連結串列。在這裡結合例子介紹會更加清楚一些。
那麼帶頭結點和不帶頭結點的區別在哪裡呢?

帶頭結點:head-->p1-->p2-->p3-->p4..........

不帶頭結點:p1-->p2-->-->p3-->p4.............

如果是環的話帶頭結點和不帶頭結點是下面這樣的

帶頭結點:head-->p1-->p2-->p3-->head-->p1..........

不帶頭結點:p1-->p2-->-->p3-->p1-->p2.............

圖解如下: ![這裡寫圖片描述](https://img-blog.csdn.net/20180916204310258?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwNTUwMDE4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
頭結點直接指向連結串列的首元素,有助於我們直接找到連結串列的第一個元素,帶頭結點的連結串列的第一個元素其實就是head->next元素,頭結點只是給我們提供了一個入口,方便我們快速找到第一個元素。當然,頭結點的位置是不能變的,不能變主要體現在頭插和頭刪的時候,如果要在帶頭結點的連結串列中頭插一個元素,那麼一定是插在頭結點後面的位置的,而不是在頭結點前面插。
##雙向帶頭迴圈連結串列 >顧名思義,這是一個雙鏈表,而且帶頭結點,還是個環。那麼本篇的重點是討論這一類常見的連結串列的插入和刪除。

首先需要頂一個雙鏈表,前面說了,雙鏈表的每個資料結點中有兩個指標,分別指向前驅結點和後繼結點。
※※※再次宣告,以下所有操作均為雙向帶頭迴圈連結串列

雙鏈表的定義

//雙鏈表的定義
typedef   int  datatype;
typedef  struct DNode{
	datatype   data;//資料域
	DNode * prev;//指向前驅結點
	DNode *next;//指向後繼結點
}Dlist;

###建立結點

//建立結點
Dlist *CreateNode(datatype  data)
{
	Dlist *node = (Dlist*)malloc(sizeof(Dlist));
	node->data = data;
	node->next = node->prev = NULL;//建立的新結點前驅和後繼都為空
	return node;
}

###初始化

//初始化
void DListInit(Dlist **ps)
{
	assert(ps);
	Dlist *node = CreateNode(0);//這裡0是無效的,因為在頭結點中
	node->next = node->prev = node;//構成環,所以建立的這個結點前驅和後繼都是本身
	*ps = node;//將建立好的結點放入連結串列中

}

這裡寫圖片描述
###列印連結串列

//列印連結串列
void DListPrint(Dlist *head)
{
	Dlist *cur = head->next;
	for (cur = head->next; cur != head; cur = cur->next)
	{
		printf("%d-->", cur->data);
	}
	printf("\n");
}

###清空

//清空連結串列
void ClearDList(Dlist *head)
{
	Dlist *cur=head->next;
	Dlist *next;
	while (cur != head)
	{
		next = cur->next;
		free(cur);
		cur = next;
	}
	head->prev = head->next = head;//清空完後只剩頭結點
}

###銷燬

//銷燬
void DestoryDList(Dlist *head)
{
	ClearDList(head);
	free(head);
}

###頭插

//頭插,插在頭結點後面
void  PushFront(Dlist *head,datatype data)
{
	Dlist *node = CreateNode(data);
	node->next = head->next;
	head->next->prev = node;
	node->prev = head;
	head->next = node;
}

這裡寫圖片描述
這裡寫圖片描述
###尾插
這裡寫圖片描述

//尾插
void PushBack(Dlist *head, datatype data)
{
	Dlist *node = CreateNode(data);
	node->prev = head->prev;
	head->prev->next = node;
	node->next = head;
	head->prev = node;
}

這裡寫圖片描述
###任意結點插入

//插入到指定位置
void Insert(Dlist *head,Dlist *pos,datatype data)
{
	Dlist *node = CreateNode(data);
	node->next = pos;
	node->prev = pos->prev;
	pos->prev->next = node;
	pos->prev = node;
}

這裡寫圖片描述
###頭刪

//頭刪
void PopFront(Dlist *head)
{
	Dlist *del = head->next;
	head->next = del->next;
	del->next->prev = head;
}

這裡寫圖片描述
###尾刪

//尾刪
void PopBack(Dlist *head)
{
	Dlist *del = head->prev;
	del->prev->next = head;
	head->prev = del->prev;
	free(del);
}

這裡寫圖片描述

###刪除任意結點

//刪除任意位置的結點
void DListerase(Dlist *head, Dlist *pos)
{
	assert(head->next != head);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;
	free(pos);
}

這裡寫圖片描述
上一篇:單鏈表https://blog.csdn.net/qq_40550018/article/details/82687292
如有紕漏請路過的大神指正!!!