国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【數(shù)據(jù)結構】C語言實現(xiàn)雙鏈表的基本操作

這篇具有很好參考價值的文章主要介紹了【數(shù)據(jù)結構】C語言實現(xiàn)雙鏈表的基本操作。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

根據(jù)所學的c語言知識,以學生基本信息為節(jié)點,構造一個包含5個元素的雙鏈表結構。,保姆級教學,數(shù)據(jù)結構,數(shù)據(jù)結構,c語言,開發(fā)語言,算法,改行學it,學習

導言

大家好,很高興又和大家見面啦?。?!

經過前面幾個篇章的內容分享,相信大家對順序表和單鏈表的基本操作都已經熟練掌握了。今天咱們將繼續(xù)分享線性表的鏈式存儲的第二種形式——雙鏈表。在今天的內容中,咱們將介紹雙鏈表的創(chuàng)建以及一些基本操作,接下來跟我一起來看看吧!

一、單鏈表與雙鏈表

線性表的鏈式存儲稱為鏈表,鏈表是由數(shù)據(jù)域和指針域組成。

由一個數(shù)據(jù)域和一個指針域組成的鏈表我們稱為單鏈表,單鏈表的指針域指向后繼結點,所以我們在訪問單鏈表時只能從前往后訪問。這就導致了一個問題:我們在訪問后繼結點時的時間復雜度為O(1),但是在訪問前驅結點時的時間復雜度卻是O(n)。

為了克服單鏈表的這種單一訪問的缺點,于是我們在單鏈表的結點上新增了一個指針域,使得鏈表上的每個結點都由一個數(shù)據(jù)域和兩個指針域組成,雙鏈表的結點結構如下所示:

根據(jù)所學的c語言知識,以學生基本信息為節(jié)點,構造一個包含5個元素的雙鏈表結構。,保姆級教學,數(shù)據(jù)結構,數(shù)據(jù)結構,c語言,開發(fā)語言,算法,改行學it,學習
這兩個指針域一個指向后繼結點(next),一個指向前驅結點(prior),我們將由這種結構的結點構成的鏈表稱為雙鏈表。

雙鏈表和單鏈表一樣,雙鏈表也有帶頭結點的雙鏈表與不帶頭結點的雙鏈表,在沒有特殊說明的情況下,我們都是以帶頭結點的雙鏈表進行說明。接下來我們就來看一下與雙鏈表相關的基本操作;

二、雙鏈表類型的創(chuàng)建

我們首先來看一下雙鏈表的類型創(chuàng)建的基本格式:

//雙鏈表類型創(chuàng)建的基本格式
typedef struct DNode {
	ElemType data;//數(shù)據(jù)域
	struct DNode* prior, * next;//指針域
}DNode, * DLinkList;//數(shù)據(jù)類型重命名
//DNode——Double Node——強調的是雙鏈表的結點
//DLinkList——強調的是指向雙鏈表的指針,也就是整個雙鏈表
//prior——在先的,在前的,先前的——指向前驅結點的指針
//next——下一個的,緊接著的,接下來的——指向后繼結點的指針
//ElemType——數(shù)據(jù)元素的數(shù)據(jù)類型
//data——存儲鏈表數(shù)據(jù)元素的變量

從格式中可以看到,其實雙鏈表與單鏈表的類型創(chuàng)建格式是一致的,它們之間的差別有以下幾點:

  1. 為了對這兩種類型的鏈表有所區(qū)分,單鏈表的結點類型我們將其定義為LNode,雙鏈表則是DNode;
  2. 單鏈表的類型我們將其定義為LinkList,雙鏈表則是DLinkList;
  3. 在雙鏈表中,我們定義了一個額外的指針prior用于指向前驅結點;

有了這個基本格式,我們同樣還是以整型類型的數(shù)據(jù)元素為例來定義一個雙鏈表,如下所示:

//創(chuàng)建雙鏈表類型
typedef struct DNode {
	int data;
	struct DNode* prior, * next;
}DNode, * DLinkList;
int main()
{
	DLinkList L;//定義指向雙鏈表的頭指針
	return 0;
}

有了雙鏈表的頭指針,接下來我們就可以來創(chuàng)建雙鏈表的頭結點并將其初始化了;

三、雙鏈表的初始化

我們先來看一下雙鏈表初始化的基本格式:

//雙鏈表初始化的基本格式
bool InitDLinkList(DLinkList* L)
{
	*L = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建頭結點
	assert(*L);//如果頭結點創(chuàng)建失敗,則報錯
	(*L)->prior = NULL;//初始化前驅指針
	(*L)->next = NULL;//初始化后繼指針
	return true;
}

可以看到,對于雙鏈表來說,我們在初始化頭結點時不僅要將后繼指針進行初始化,還要將前驅指針進行初始化,這樣是為了防止這兩個指針變成野指針。

  • 在單鏈表中有一點我們沒有提到,就是我們在通過malloccalloc申請空間后一定要及時的對接收空間的指針進行檢測,看是否為空指針。

  • 當空間申請失敗后,這兩個函數(shù)返回的就是一個空指針,所以為了避免出現(xiàn)問題,我們可以通過assert來進行斷言,也可以通過條件語句來進行判斷。

  • 對指針這一塊的知識掌握的不牢固的朋友可以通過【C語言必學知識點五】指針這篇博客來復習一下指針的相關知識點

我們在對雙鏈表初始化之后就可以來通過頭插法或者尾插法來創(chuàng)建一個雙鏈表了;

四、雙鏈表的創(chuàng)建

由于雙鏈表的結點結構與單鏈表的結點結構不同,因此我們在創(chuàng)建雙鏈表時的邏輯也是稍有區(qū)別的,如下圖所示:

根據(jù)所學的c語言知識,以學生基本信息為節(jié)點,構造一個包含5個元素的雙鏈表結構。,保姆級教學,數(shù)據(jù)結構,數(shù)據(jù)結構,c語言,開發(fā)語言,算法,改行學it,學習
由于多了一個前驅結點,這就導致我們在創(chuàng)建鏈表時通過頭插法在創(chuàng)建第一個表頭元素與創(chuàng)建其他的表頭元素的步驟稍有不同,如下所示;

用頭插法創(chuàng)建第一個表頭結點的步驟:

  1. 新結點的后繼指針指向頭結點的后繼指針指向的對象,即NULL;
  2. 新結點的前驅指針指向頭結點;
  3. 頭結點的后繼指針指向新結點;

用C語言來描述的話則是:

//頭插法創(chuàng)建第一個表頭結點的插入步驟
New_Node->next = Head->next;//新結點的后繼指針指向頭結點后繼指針指向的對象,即NULL
New_Node->prior = Head;//新結點的前驅指針指向頭結點
Head->next = New_Node;//頭結點的后繼指針指向新結點
  • 注:這個插入順序要確保第3步的操作一定在第1步操作完后再執(zhí)行;第2步的操作順序可以隨意放置;

用頭插法創(chuàng)建第二個及以上的表頭結點的步驟:

  1. 新結點的后繼指針指向頭結點的后繼指針指向的對象,即表頭結點;
  2. 頭結點后繼指針指向對象的前驅結點指向新結點;
  3. 新結點的前驅指針指向頭結點;
  4. 頭結點的后繼指針指向新結點;

用C語言描述的話則是:

//頭插法創(chuàng)建第二個及以上的頭結點的插入步驟
New_Node->next = Head->next;//新結點的后繼指針指向頭結點后繼指針指向的對象,即NULL
Head->next->prior = New_Node;//頭指針的后繼指針指向對象的前驅指針指向新結點
New_Node->prior = Head;//新結點的前驅指針指向頭結點
Head->next = New_Node;//頭結點的后繼指針指向新結點
  • 注:這個插入順序要確保第4步的操作一定在第1步與第2步操作完之后執(zhí)行;第3步操作的順序可以隨意放置;

接下來我們來看一下在這個邏輯下的雙鏈表的頭插法的基本格式:

//頭插法創(chuàng)建雙鏈表的基本格式
DLinkList DList_HeadInsert(DLinkList* L)
{
	DNode* p;//指向新結點的指針
	ElemType x = 0;//接收數(shù)據(jù)元素的變量
	……;//獲取需要存儲的數(shù)據(jù)元素
	while (x != EOF)//通過給循環(huán)設置結束條件來控制創(chuàng)建的結束
	{
		p = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
		assert(p);//當創(chuàng)建新結點失敗時,assert會對指針p進行報錯
		if (!(*L)->next)//當頭結點的后繼指針指向空指針時
		{
			p->data = x;//將數(shù)據(jù)元素存儲到新結點的數(shù)據(jù)域中
			p->next = (*L)->next;//新結點的后繼指針指向頭結點后繼指針指向的對象
			p->prior = *L;//新結點的前驅指針指向頭結點
			(*L)->next = p;//頭結點的后繼指針指向新結點
		}
		else
		{
			p->data = x;//將數(shù)據(jù)元素存儲到新結點的指針域中
			p->next = (*L)->next;//新結點的后繼指針指向頭結點后繼指針指向的對象
			(*L)->next->prior = p;//頭結點的后繼指針指向的對象的前驅指針指向新結點
			p->prior = *L;//新結點的前驅指針指向頭結點
			(*L)->next = p;//頭結點的后繼指針指向新結點
		}
		……;//獲取需要存儲的數(shù)據(jù)元素
	}
	return (*L);//創(chuàng)建好鏈表后返回頭指針
}

但是對于尾插法而言,不管是第一個結點還是最后一個結點的創(chuàng)建,在插入步驟上都是不影響的,因為表尾結點的后繼指針肯定是指向NULL的,因此通過尾插法創(chuàng)建的雙鏈表則不需要分情況討論,對應的尾插法創(chuàng)建格式如下所示:

//尾插法創(chuàng)建雙鏈表的基本格式
DLinkList DList_TailInsert(DLinkList* L)
{
	DNode* r = *L;//指向表尾的指針
	DNode* s;//指向新結點的指針
	ElemType x = 0;//接收數(shù)據(jù)元素的變量
	……;//獲取需要存儲的數(shù)據(jù)元素
	while (x != EOF)//通過給循環(huán)設置結束條件來控制創(chuàng)建的結束
	{
		s = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
		assert(s);
		s->data = x;//將數(shù)據(jù)元素存儲到新結點的數(shù)據(jù)域中
		s->next = r->next;//新結點的后繼指針指向表尾結點的后繼指針,即NULL
		s->prior = r;//新結點的前驅指針指向表尾結點
		r->next = s;//表尾結點的后繼指針指向新結點
		r = s;//表尾指針指向新結點
		……;//獲取新的數(shù)據(jù)元素
	}
	return(*L);//當鏈表創(chuàng)建結束,返回頭指針
}

在創(chuàng)建好雙鏈表后,我們又該如何遍歷雙鏈表來訪問某個結點呢?

五、雙鏈表的遍歷

在給定一個結點后要想對單鏈表進行遍歷的話,我們只能從該結點往后遍歷,但是在雙鏈表中,我們既可以從給定結點開始往后遍歷,又可以從給定結點開始往前遍歷。遍歷的方式也很簡單,我們只需要將指向雙鏈表的指針往我們需要遍歷的方向進行移動就行,如下所示:

//給定結點指針p遍歷雙鏈表
while (p->next)//p的后繼結點不為空指針
{
	p = p->next;//從結點p往后遍歷
}
while (p->prior)//p的前驅結點不為空指針
{
	p = p->prior;//從結點p往前遍歷
}

想要對某一個結點進行想過操作時,我們就可以通過這個遍歷的方式來找到對應結點并執(zhí)行相關操作。

六、雙鏈表的查找

由于雙鏈表是與前驅結點以及后繼結點進行雙向鏈接的,因此我們在給定雙鏈表的一個結點后,不管是查找該結點的后繼結點還是前驅結點,對應的時間復雜度都為O(1);

在未給定結點的情況下,我們要想查找對應的結點,我們同樣可以通過按值查找與按位查找兩種查找方式來執(zhí)行,下面我們來看一下在雙鏈表中,這兩種查找方式的基本格式又是如何:

//雙鏈表的按位查找
DNode* GetElem(DLinkList L, int i)
{
	if (i < 1)
		return NULL;//當查找的位序不合理時返回空指針
	DNode* p = L->next;//指向表頭結點的指針
	int j = 1;//表頭結點的位序
	while (p && j < i)//當查找結點為空指針時結束循環(huán);當查找結點的位序與目標位序相等時結束循環(huán)
	{
		p = p->next;//繼續(xù)往后遍歷
		j++;
	}
	return p;//查找結束后返回指針p
}

如果是已知某一個結點的位序,需要查找另一個結點的位序,我們可以將函數(shù)的參數(shù)換成已知的結點以及需要查找的結點位序就行,這里就不再展開。下面我們來看一下按值查找的基本格式:

//雙鏈表的按位查找
DNode* LocateElem(DLinkList L, ElemType e)
{
	DNode* p = L->next;//指向表頭結點的指針
	while (p && p->data != e)//當查找結點為空指針時結束循環(huán)
	//當查找結點的數(shù)據(jù)域存儲的元素與目標元素相等時結束循環(huán)
	{
		p = p->next;//繼續(xù)往后遍歷
	}
	return p;//查找結束后返回指針p
}

對于雙鏈表而言,在進行查找操作時對應的時間復雜度就有以下幾種情況:

  • 如果是從表頭結點或者表尾結點開始進行查找的話,那對應的時間復雜度就是O(n);
  • 如果是已知結點要查找對應的前驅結點或者后繼結點的話,那對應的時間復雜度就是O(1);
  • 如果是已知某一結點,需要查找位序在該結點前面或者后面的結點的話,那對應的時間復雜度就是O(n);

七、雙鏈表的插入

雙鏈表的插入操作也是有前插與后插操作,前插操作的邏輯與單鏈表一致,都是通過在指點結點的后面插入一個新的結點,再對數(shù)據(jù)域中存儲的數(shù)據(jù)進行移動從而完成前插操作,下面我們先來看一下雙鏈表前插操作的基本格式:

//雙鏈表的前插操作
bool InsertPriorDNode(DNode* p, ElemType e)
{
	assert(p);//指針p為空指針時報錯
	DNode* q = p->prior;//指針p的前驅結點
	assert(q);//指針q為空指針時報錯
	DNode* s = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
	assert(s);//指針s為空指針時報錯
	s->data = e;//將要插入的元素e放入新結點的數(shù)據(jù)域中
	s->next = p;//將新結點的后繼指針指向進行前插操作的結點p
	p->prior = s;//將結點p的前驅指針指向新結點s
	q->next = s;//將前驅結點的后繼指針指向新結點s
	s->prior = q;//將新結點的前驅指針執(zhí)行前驅結點q
	return true;//完成前插操作后返回true
}

在雙鏈表中進行前插操作時,我們有幾點需要注意:

  1. 首先要確定該結點不是頭結點,也就是該結點的前驅結點不為空指:
    • 當該結點為頭結點時,不能進行前插操作,此時給予一定的信息進行提示;
    • 當該結點不為頭結點時,則可以正常進行前插操作;
  2. 因為雙鏈表結點的前驅指針直接指向的是前驅結點,因此我們不需要像單鏈表一樣調用函數(shù)來查找前驅結點;
  3. 在進行插入操作時,前驅結點的后繼指針執(zhí)行新結點的操作最好放在最后一步執(zhí)行;

下面我們來看一下雙鏈表的后插操作:

//雙鏈表的后插操作
bool InsertNextDNode(DNode* p, ElemType e)
{
	assert(p);//指針p為空指針時報錯
	DNode* s = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
	assert(s);//指針s為空指針時報錯
	s->data = e;//將要插入的數(shù)據(jù)放入新結點的數(shù)據(jù)域中
	if (p->next)//結點p的后繼結點不為空指針
	{
		s->next = p->next;//將新結點的后繼指針指向結點p的后繼結點
		p->next->prior = s;//結點p的后繼結點的前驅指針執(zhí)行新結點
		s->prior = p;//新結點的前驅指針指向結點p
		p->next = s;//結點p的后繼指針指向新結點
	}
	else//結點p的后繼結點為空指針
	{
		s->next = p->next;//將新結點的后繼指針指向結點p的后繼結點
		s->prior = p;//新結點的前驅指針指向結點p
		p->next = s;//結點p的后繼指針指向新結點
	}
	return true;//完成后插操作后返回true
}

在雙鏈表中我們要執(zhí)行后插操作,我們也需要注意幾點:

  1. 要判斷當前結點的后繼結點是否為空指針,從而選擇插入操作的執(zhí)行步驟:
    • 當前結點的后繼結點不為空指針時,需要將后繼結點的前驅指針的指向對象換成新結點;
    • 當前結點的后繼結點為空指針時,只需要將新結點的后繼指針指向空指針就行
  2. 不管當前結點的后繼結點是否為空指針,我們最好都是將當前結點的后繼指針指向新結點的操作放在最后執(zhí)行;

對于雙鏈表而言,不管是前插操作還是后插操作,其對應的時間復雜度都是O(1),相比于單鏈表,雙鏈表的執(zhí)行效率會更高;

八、雙鏈表的刪除

如果我想刪除雙鏈表中的某個結點時,我們只需要按照以下步驟就能完成刪除操作:

  1. 將當前結點的前驅結點的后繼指針指向當前結點的后繼結點;
  2. 將當前結點的后繼結點的前驅指針指向當前結點的前驅結點;
  3. 釋放當前結點的空間;

將其轉換成C語言則是:

//雙鏈表的刪除操作
DNode->prior->next = DNode->next;//將前驅結點的后繼指針指向后繼結點
DNode->next->prior = DNode->prior;//將后繼結點的前驅指針指向前驅結點
free(DNode);//釋放當前結點的內存空間

如果是刪除的結點為表尾結點,則我們只需要將表尾結點的前驅結點指向空指針,然后直接釋放表尾結點的空間就行,轉換成C語言則是如下所示:

//刪除表尾結點
DNode->prior->next = NULL;//表尾結點的前驅結點的后繼指針指向空指針
DNode->prior->next = DNode->next;//前驅結點的后繼指針,指向后繼結點,即空指針
free(DNode);//釋放表尾結點的內存空間

刪除表尾結點時,第一句代碼與第二句代碼都是可以使用的,效果都一樣,二者選其一就行。下面我們將刪除操作封裝成一個函數(shù)的話,則對應的格式如下所示:

//雙鏈表的刪除操作
bool DeleteDNode(DNode* p)
{
	assert(p);//指針p為空指針時報錯
	DNode* q = p->prior;//p的前驅結點
	assert(q);//當q為空指針時報錯
	DNode* r = p->next;//p的后繼結點
	if (r)//后繼結點不為空指針時
	{
		q->next = r;//前驅結點指向后繼結點
		r->prior = q;//后繼結點指向前驅結點
		free(p);//釋放結點p的內存
	}
	else
	{
		q->next = r;//前驅結點指向后繼結點,即空指針
		free(p);//釋放結點p的內存
	}
	return true;//完成刪除操作后返回true
}

當對結點進行前刪或者后刪時,也是相同的邏輯,這不過在這個基礎上做一點小小的變動,這里我就不展開介紹了。當我們相對整個雙鏈表進行刪除時,我們只需要重復刪除表尾結點的操作即可,大家有興趣的話可以自己嘗試著編寫一下;

九、雙鏈表基本操作完整代碼展示

今天涉及到的代碼如下所示,需要的朋友可以自?。?/p>

//創(chuàng)建雙鏈表類型
typedef struct DNode {
	int data;
	struct DNode* prior, * next;
}DNode, * DLinkList;
//初始化雙鏈表
bool InitDLinkList(DLinkList* L)
{
	*L = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建頭結點
	assert(*L);//如果頭結點創(chuàng)建失敗,則報錯
	(*L)->prior = NULL;//初始化前驅指針
	(*L)->next = NULL;//初始化后繼指針
	return true;
}
//尾插法創(chuàng)建雙鏈表
DLinkList DList_TailInsert(DLinkList* L)
{
	DNode* r = *L;//指向表尾的指針
	DNode* s;//指向新結點的指針
	int x = 0;//接收數(shù)據(jù)元素的變量
	while (scanf("%d", &x) == 1)//通過給循環(huán)設置結束條件來控制創(chuàng)建的結束
	{
		s = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
		assert(s);
		s->data = x;//將數(shù)據(jù)元素存儲到新結點的數(shù)據(jù)域中
		s->next = r->next;//新結點的后繼指針指向表尾結點的后繼指針,即NULL
		s->prior = r;//新結點的前驅指針指向表尾結點
		r->next = s;//表尾結點的后繼指針指向新結點
		r = s;//表尾指針指向新結點
	}
	return(*L);//當鏈表創(chuàng)建結束,返回頭指針
}
//雙鏈表的按位查找
DNode* GetElem(DLinkList L, int i)
{
	if (i < 1)
		return NULL;//當查找的位序不合理時返回空指針
	DNode* p = L->next;//指向表頭結點的指針
	int j = 1;//表頭結點的位序
	while (p && j < i)//當查找結點為空指針時結束循環(huán);當查找結點的位序與目標位序相等時結束循環(huán)
	{
		p = p->next;//繼續(xù)往后遍歷
		j++;
	}
	return p;//查找結束后返回指針p
}
//雙鏈表的按值查找
DNode* LocateElem(DLinkList L, int e)
{
	DNode* p = L->next;//指向表頭結點的指針
	while (p && p->data != e)//當查找結點為空指針時結束循環(huán);當查找結點的數(shù)據(jù)域存儲的元素與目標元素相等時結束循環(huán)
	{
		p = p->next;//繼續(xù)往后遍歷
	}
	return p;//查找結束后返回指針p
}
//雙鏈表的前插操作
bool InsertPriorDNode(DNode* p, int e)
{
	assert(p);//指針p為空指針時報錯
	DNode* q = p->prior;//指針p的前驅結點
	assert(q);//指針q為空指針時報錯
	DNode* s = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
	assert(s);//指針s為空指針時報錯
	s->data = e;//將要插入的元素e放入新結點的數(shù)據(jù)域中
	s->next = p;//將新結點的后繼指針指向進行前插操作的結點p
	p->prior = s;//將結點p的前驅指針指向新結點s
	q->next = s;//將前驅結點的后繼指針指向新結點s
	s->prior = q;//將新結點的前驅指針執(zhí)行前驅結點q
	return true;//完成前插操作后返回true
}
//雙鏈表的后插操作
bool InsertNextDNode(DNode* p, int e)
{
	assert(p);//指針p為空指針時報錯
	DNode* s = (DNode*)calloc(1, sizeof(DNode));//創(chuàng)建新結點
	assert(s);//指針s為空指針時報錯
	s->data = e;//將要插入的數(shù)據(jù)放入新結點的數(shù)據(jù)域中
	if (p->next)//結點p的后繼結點不為空指針
	{
		s->next = p->next;//將新結點的后繼指針指向結點p的后繼結點
		p->next->prior = s;//結點p的后繼結點的前驅指針執(zhí)行新結點
		s->prior = p;//新結點的前驅指針指向結點p
		p->next = s;//結點p的后繼指針指向新結點
	}
	else//結點p的后繼結點為空指針
	{
		s->next = p->next;//將新結點的后繼指針指向結點p的后繼結點
		s->prior = p;//新結點的前驅指針指向結點p
		p->next = s;//結點p的后繼指針指向新結點
	}
	return true;//完成后插操作后返回true
}
//雙鏈表的刪除操作
bool DeleteDNode(DNode* p)
{
	assert(p);//指針p為空指針時報錯
	DNode* q = p->prior;//p的前驅結點
	assert(q);//當q為空指針時報錯
	DNode* r = p->next;//p的后繼結點
	if (r)//后繼結點不為空指針時
	{
		q->next = r;//前驅結點指向后繼結點
		r->prior = q;//后繼結點指向前驅結點
		free(p);//釋放結點p的內存
	}
	else
	{
		q->next = r;//前驅結點指向后繼結點,即空指針
		free(p);//釋放結點p的內存
	}
	return true;//完成刪除操作后返回true
}
//打印雙鏈表
void Print_DLinkList(DLinkList L)
{
	printf("打印雙鏈表:>");
	DNode* p = L->next;
	for (p; p; p = p->next)
		printf("%d ", p->data);
	printf("\n");
}
int main()
{
	DLinkList L;//定義指向雙鏈表的頭指針
	InitDLinkList(&L);//初始化雙鏈表
	DList_TailInsert(&L);//尾插法創(chuàng)建雙鏈表
	Print_DLinkList(L);//打印雙鏈表
	DNode* p = GetElem(L, 3);//按位查找
	if (p)
	{
		printf("\n找到位序為%d的結點p了,該結點的地址為%p\n", 3, p);
	}
	if(InsertPriorDNode(p, 2))
	{
		printf("成功在結點p前插入了一個存放%d的新結點\n", 2);
		Print_DLinkList(L);//打印雙鏈表
	}
	DNode* p2 = LocateElem(L, 5);//按值查找
	if (p2)
	{
		printf("\n找到存放%d的結點p2了,該結點的地址為%p\n", 5, p2);
	}
	if (InsertNextDNode(p2, 6))
	{
		printf("成功在結點p后插入了一個存放%d的新結點\n", 6);
		Print_DLinkList(L);//打印雙鏈表
	}
	if (DeleteDNode(p2))
	{
		printf("\n成功刪除了結點p2\n");
		Print_DLinkList(L);//打印雙鏈表
	}
	return 0;
}

結語

雙鏈表的內容到這里咱們就全部介紹完了,在今天的篇章中,咱們詳細介紹了雙鏈表的創(chuàng)建、初始化、查找、插入、刪除等基本操作,并給大家附上了對應操作的代碼。希望今天的內容能夠幫助大家更好的理解雙鏈表及其基本操作。

在下一篇內容中,咱們將介紹循環(huán)鏈表以及靜態(tài)鏈表的相關內容,大家記得關注哦!?。∽詈蟾兄x各位的翻閱,咱們下一篇再見!文章來源地址http://www.zghlxwxcb.cn/news/detail-767460.html

到了這里,關于【數(shù)據(jù)結構】C語言實現(xiàn)雙鏈表的基本操作的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 【數(shù)據(jù)結構】順序表的實現(xiàn)及基本操作完整代碼(C語言實現(xiàn))

    【數(shù)據(jù)結構】順序表的實現(xiàn)及基本操作完整代碼(C語言實現(xiàn))

    順序表:邏輯上相鄰的數(shù)據(jù)元素,其物理次序也是相鄰的 這里之所以要把int分別創(chuàng)建新名字為SqlElemType和Status,是因為實際應用時數(shù)據(jù)的類型不一定是int型,這樣設置方便修改元素類型,提高代碼適用性。 LocateElem的時間復雜度為O(n) InsertSq的時間復雜度為O(n) DeleteSq的時間

    2024年04月12日
    瀏覽(25)
  • 數(shù)據(jù)結構(C語言實現(xiàn))——順序表的介紹及基本操作的實現(xiàn)

    今天我們來學習數(shù)據(jù)結構中的線性表,本文主要介紹一種常見的線性表——順序表。 本文著重介紹順序表的概念以及順序表各種基本操作的實現(xiàn)過程(C語言實現(xiàn)),以后會更新更多的數(shù)據(jù)結構,覺得有用的朋友可以三連關注一波,一起學習。 線性表(linear list)是n個具有相

    2023年04月13日
    瀏覽(22)
  • 【Java數(shù)據(jù)結構 -- 實現(xiàn)雙鏈表的接口方法】

    【Java數(shù)據(jù)結構 -- 實現(xiàn)雙鏈表的接口方法】

    雙鏈表是一種數(shù)據(jù)結構,其中每個節(jié)點包含 一個指向前一個節(jié)點的指針和一個指向后一個節(jié)點的指針 。由于鏈表沒有將元素存儲在連續(xù)的空間中,元素存儲在單獨的節(jié)點中,然后通過引用將節(jié)點連接起來,因此雙鏈表可以任意且快速的插入和刪除元素。 引用接口IList,在把

    2024年01月16日
    瀏覽(98)
  • Java 數(shù)據(jù)結構篇-實現(xiàn)雙鏈表的核心API

    Java 數(shù)據(jù)結構篇-實現(xiàn)雙鏈表的核心API

    ??博客主頁:? 小扳_-CSDN博客 ?感謝大家點贊??收藏?評論? ? ? ? 文章目錄 ? ? ? ? 1.0 雙鏈表的說明 ? ? ? ? 1.1 雙鏈表 - 創(chuàng)建 ? ? ? ? 1.2 雙鏈表 - 根據(jù)索引查找節(jié)點 ? ? ? ? 1.3 雙鏈表 -?根據(jù)索引插入節(jié)點 ? ? ? ? 1.4 雙鏈表 -?頭插節(jié)點 ? ? ? ? 1.5 雙鏈表 - 尾插

    2024年02月04日
    瀏覽(91)
  • 【數(shù)據(jù)結構】單鏈表的基本操作 (C語言版)

    【數(shù)據(jù)結構】單鏈表的基本操作 (C語言版)

    目錄 一、單鏈表 1、單鏈表的定義: 2、單鏈表的優(yōu)缺點: 二、單鏈表的基本操作算法(C語言) 1、宏定義 2、創(chuàng)建結構體 3、初始化 4、插入 4、求長度 5、清空 6、銷毀? 7、取值 8、查找 9、刪除 10、頭插法創(chuàng)建單鏈表 11、尾插法創(chuàng)建單鏈表 三、單鏈表的全部代碼(C語言)

    2024年01月22日
    瀏覽(93)
  • 【數(shù)據(jù)結構】 循環(huán)單鏈表的基本操作 (C語言版)

    【數(shù)據(jù)結構】 循環(huán)單鏈表的基本操作 (C語言版)

    目錄 一、循環(huán)單鏈表 1、循環(huán)單鏈表的定義: 2、循環(huán)單鏈表的優(yōu)缺點: 二、循環(huán)單鏈表的基本操作算法(C語言)?? ?1、宏定義 ?2、創(chuàng)建結構體 3、循環(huán)單鏈表的初始化? 4、循環(huán)單鏈表的插入 5、求單鏈表長度 6、循環(huán)單鏈表的清空 7、循環(huán)單鏈表的銷毀 8、循環(huán)單鏈表的取

    2024年01月22日
    瀏覽(93)
  • C語言---數(shù)據(jù)結構實驗---順序表的合并---鏈表的基本操作---重點解析約瑟夫問題

    C語言---數(shù)據(jù)結構實驗---順序表的合并---鏈表的基本操作---重點解析約瑟夫問題

    實驗的寫法多種多樣,但本文并未采用 #define 定義容量的寫法,這樣寫已經是很老舊過時的寫法。所有實驗主體采用均為動態(tài)開辟,后續(xù)如果利用 C++ 來寫或許會應用更多語法… 本篇展示數(shù)據(jù)結構的兩個實驗 其中,重點分析約瑟夫問題 實驗中代碼的命名風格等均與下方博客

    2024年02月16日
    瀏覽(96)
  • 【數(shù)據(jù)結構】雙鏈表的定義和操作

    【數(shù)據(jù)結構】雙鏈表的定義和操作

    目錄 1.雙鏈表的定義 2.雙鏈表的創(chuàng)建和初始化 3.雙鏈表的插入節(jié)點操作 4.雙鏈表的刪除節(jié)點操作 5.雙鏈表的查找節(jié)點操作 6.雙鏈表的更新節(jié)點操作 7.完整代碼 ??嗨!我是Filotimo__??。很高興與大家相識,希望我的博客能對你有所幫助。 ??本文由Filotimo__??原創(chuàng),首發(fā)于CS

    2024年02月03日
    瀏覽(93)
  • 數(shù)據(jù)結構-線性表的順序表基本操作代碼實現(xiàn)(超級詳細清晰 C++實現(xiàn))

    數(shù)據(jù)結構-線性表的順序表基本操作代碼實現(xiàn)(超級詳細清晰 C++實現(xiàn))

    順序表是用一段 物理地址連續(xù)的存儲單元 依次存儲數(shù)據(jù)元素的線性結構,一般情況下采用數(shù)組存儲。在數(shù)組上完成數(shù)據(jù)的增刪查改。 順序表: 可動態(tài)增長的數(shù)組,要求數(shù)據(jù)是連續(xù)存儲的 特點: 隨機訪問 順序既可以 靜態(tài)分配 ,也可以 動態(tài)分配 。在靜態(tài)分配時,由于數(shù)組

    2024年02月07日
    瀏覽(23)
  • 數(shù)據(jù)結構之雙鏈表的相關知識點及應用

    數(shù)據(jù)結構之雙鏈表的相關知識點及應用

    ?找往期文章包括但不限于本期文章中不懂的知識點: 個人主頁 :我要學編程(?_?)-CSDN博客 所屬專欄 :數(shù)據(jù)結構 目錄 雙鏈表的實現(xiàn)? 初始化雙鏈表? 在雙鏈表中尾插數(shù)據(jù)? 在雙鏈表中尾刪數(shù)據(jù) 在雙鏈表中頭插數(shù)據(jù)? 在雙鏈表中頭刪數(shù)據(jù)? 在雙鏈表中的指定位置之后插入

    2024年04月26日
    瀏覽(95)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包