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

『初階數(shù)據(jù)結構 ? C語言』⑨ - 基于結點的數(shù)據(jù)結構——鏈表(單鏈表&&雙向循環(huán)鏈表)附完整源碼

這篇具有很好參考價值的文章主要介紹了『初階數(shù)據(jù)結構 ? C語言』⑨ - 基于結點的數(shù)據(jù)結構——鏈表(單鏈表&&雙向循環(huán)鏈表)附完整源碼。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

?文章來源地址http://www.zghlxwxcb.cn/news/detail-598091.html

本章內(nèi)容

1.什么是鏈表

2.鏈表常見幾種形式

3.無頭單向非循環(huán)鏈表的實現(xiàn)

3.1結點結構的定義

3.2函數(shù)接口的實現(xiàn)

3.2.1尾插

3.2.2尾刪

4. 帶頭雙向循環(huán)鏈表的實現(xiàn)

4.1結點結構的定義

4.2函數(shù)接口的實現(xiàn)

5.兩種鏈表的差異

①尾插與尾刪的時間復雜度

②頭插與頭刪的時間復雜度

③函數(shù)形參為何一個是二級指針,一個是一級指針?

完整源碼

無頭單向非循環(huán)鏈表

SList.h

SList.c

test.c

帶頭雙向循環(huán)鏈表

List.h

List.c

test.c


鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言?

?

1.什么是鏈表

像數(shù)組一樣,鏈表也用來表示一系列的元素。事實上,能用數(shù)組來做的事情,一般也可以用鏈表來做。然而,鏈表的實現(xiàn)跟數(shù)組是不一樣的,在不同場景它們會有不同的性能表現(xiàn)。

計算機的內(nèi)存就像一大堆格子,每格都可以用來保存比特形式的數(shù)據(jù)。當要創(chuàng)建數(shù)組時,程序會在內(nèi)存中找出一組連續(xù)的空格子,給它們起個名字,以便你的應用存放數(shù)據(jù)。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

我們之前說過,計算機能夠直接跳到數(shù)組的某一索引上。如果代碼要求它讀取索引 4的值,那么計算機只需一步就可以完成任務。重申一次,之所以能夠這樣,是因為程序事先知道了數(shù)組開頭所在的內(nèi)存地址——例如地址是 1000——當它想去索引 4時,便會自動跳到 1004處。

與數(shù)組不同的是,組成鏈表的格子不是連續(xù)的。它們可以分布在內(nèi)存的各個地方。這種不相鄰的格子,就叫作結點

那么問題來了,計算機怎么知道這些分散的結點里,哪些屬于這個鏈表,哪些屬于其他鏈表呢?這就是鏈表的關鍵了:每個結點除了保存數(shù)據(jù),它還保存著鏈表里的下一結點的內(nèi)存地址。

這份用來指示下一結點的內(nèi)存地址的額外數(shù)據(jù),被稱為鏈。鏈表如下圖所示。?

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

注意:

1.從上圖可以看出,鏈式結構在邏輯上是來連續(xù)的,但是在物理上不一定連續(xù)。

2.現(xiàn)實中的結點一般都是從堆上來申請的。

3.從堆上申請的空間,是按照一定的策略來分配的,兩次申請的空間可能連續(xù),也可能不連續(xù)。


2.鏈表常見幾種形式

①單向或者雙向

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

②帶頭或者不帶頭?

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言?③循環(huán)或者非循環(huán)

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

雖然有這么多的鏈表的結構,但是我們實際中最常用到的還是這兩種結構:

1. 無頭單向非循環(huán)鏈表

結構簡單,一般不會用來單獨進行存儲數(shù)據(jù)。實際中更多是作為其它數(shù)據(jù)結構的子結構,如哈希表、圖的鄰接表等等。另外這種結構在筆試面試中出現(xiàn)比較多。鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

2. 帶頭雙向循環(huán)鏈表

結構最復雜,一般用于單獨存儲數(shù)據(jù)。實際中使用的鏈表數(shù)據(jù)結構,都是帶頭雙向循環(huán)鏈表。另外這個結構雖然結構復雜,但是使用代碼實現(xiàn)以后發(fā)現(xiàn)結構會帶來很多優(yōu)勢,實現(xiàn)反而簡單了。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言


3.無頭單向非循環(huán)鏈表的實現(xiàn)

就我個人而言,我認為雖然無頭單向非循環(huán)鏈表是這幾個鏈表中結構最簡單的,但是實現(xiàn)卻是最復雜的。我們學會了頭單向非循環(huán)鏈表的實現(xiàn),別的鏈表實現(xiàn)應當不在話下。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

3.1結點結構的定義

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

如上文所講,一個結點包含的內(nèi)容有數(shù)據(jù)data和保存下一個結點的地址的指針。

鏈表正式由一個個這樣的結點串連起來的,所以我們只需要記住排在最前面的頭結點的位置,就能訪問鏈表里任意一個結點。

注意:無頭單向非循環(huán)鏈表里的頭結點指的是鏈表中的第一個結點,它本身也存儲著有效數(shù)據(jù)。而后面所講的帶頭雙向循環(huán)鏈表中的頭結點僅僅是作為鏈表起始的標志,并不會存儲有效數(shù)據(jù)。

3.2函數(shù)接口的實現(xiàn)

//申請一個結點
SLTNode* BuySLTNode(SLTDataType data);
//創(chuàng)建一個鏈表,包含數(shù)據(jù)為0~n
SLTNode* CreateSList(int n);
//釋放內(nèi)存
void SLTDestroy(SLTNode** pphead);
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType data);
//尾刪
void SLTPopBack(SLTNode** pphead);
//頭插
void SLTPushFront(SLTNode** pphead, SLTDataType data);
//頭刪
void SLTPopFront(SLTNode** pphead);
//查找data的結點
SLTNode* SLTFind(SLTNode** pphead, SLTDataType data);
//在pos位置前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType data);
//在pos位置后插入
void SLTInsertAfter(SLTNode* pos, SLTDataType data);
//刪除pos結點
void SLTErase(SLTNode** pphead, SLTNode* pos);
//打印鏈表內(nèi)容
void SLTPrint(SLTNode* phead);

由于代碼量過大,為了避免影響閱讀體驗太差,我將完整代碼置于文章末尾。此處,我們來細致的學習兩個函數(shù)尾插與尾刪,其它函數(shù)與其原理幾乎相同。

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType data);
//尾刪
void SLTPopBack(SLTNode** pphead);

3.2.1尾插

void SLTPushBack(SLTNode** pphead, SLTDataType data)
{
	SLTNode* newNode = BuySLTNode(data);
	//若為第一次插入,則分情況處理
	if (*pphead==NULL)
	{
		*pphead = newNode;
		return;
	}

	//找尾
	SLTNode* tail = *pphead;
	while(tail->next)
	{
		tail = tail->next;
	}
	//找到了,進行尾插
	tail->next = newNode;
}

?首先將tail也指向頭結點,通過變化tail來找到尾結點,如下圖所示為找尾的過程:

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

此時,tail所指向的結點的next為NULL,則循環(huán)結束,進行尾插。尾插只需要將tail所指向的結點的next指針賦值為newNode即可。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

3.2.2尾刪

void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	//分情況處理
	if (*pphead == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}

	//找尾
	SLTNode* tail = *pphead;
	while (tail->next->next)
	{
		tail = tail->next;
	}
	//找到了,進行尾刪
	free(tail->next);
	tail->next = NULL;
}

同樣的尾刪也是先找尾,但與尾插的找尾有一點不同的是while循環(huán)的判斷條件不相同。原因是我們刪掉尾結點后,還有重要的一步是將尾結點的前一個結點(也就是新的尾結點)的next置為NULL。所以這里的tail指向的是尾結點的前一個結點。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

此時tail->next->next?為NULL,所以循環(huán)結束,進行尾刪。尾刪只需要釋放掉尾結點,并將新的尾結點的next置為NULL。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言


4. 帶頭雙向循環(huán)鏈表的實現(xiàn)

帶頭雙向循環(huán)鏈表看似結構復雜,其實在寫代碼時你會感到很輕松。其關鍵就在于它的頭結點不一般。此處的頭結點不存儲有效數(shù)據(jù)。

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

4.1結點結構的定義

typedef int LTDataType;

typedef struct ListNode
{
	LTDataType data;
	struct ListNode* prev;//指向前一個結點
	struct ListNode* next;//指向后一個結點
}LTNode;

既然是雙向循環(huán)鏈表,那就得要求每個結點既保存下一個結點的地址,又要保存上一個結點的地址。結構中,prev指向前一個結點,next指向后一個結點。

4.2函數(shù)接口的實現(xiàn)

//申請一個結點
LTNode* BuyListNode(LTDataType data);
//初始化頭結點
LTNode* LTInit();
//釋放申請的內(nèi)存
void LTDestroy(LTNode* phead);
//尾插
void LTPushBack(LTNode* phead, LTDataType data);
//尾刪
void LTPopBack(LTNode* phead);
//頭插
void LTPushFront(LTNode* phead, LTDataType data);
//頭刪
void LTPopFront(LTNode* phead);
//查找data
LTNode* LTFind(LTNode* phead, LTDataType data);
//在pos位置前插入
void LTInsert(LTNode* phead, LTNode* pos, LTDataType data);
//刪除pos位置
void LTErase(LTNode* phead, LTNode* pos);
//判斷鏈表是否為空
bool LTEmpty(LTNode* phead);
//統(tǒng)計鏈表中數(shù)據(jù)的個數(shù)
size_t LTSize(LTNode* phead);
//打印鏈表存儲的數(shù)據(jù)
void LTPrint(LTNode* phead);

同樣的,由于代碼過長,為了避免影響閱讀體驗,我將完整源碼置于文章末尾。帶頭雙向循環(huán)鏈表的各個函數(shù)實現(xiàn)都比不帶頭的單鏈表簡單很多。因此學會了之前單鏈表的實現(xiàn),雙向鏈表的實現(xiàn)自然輕松無比。這里就不做贅述。


5.兩種鏈表的差異

①尾插與尾刪的時間復雜度

對于單鏈表而言,尾插與尾刪都是它的劣勢。因為計算機無法直接訪問到鏈表的尾結點,必須遍歷完整個鏈表才能找到尾結點。所以單鏈表的尾插與尾刪都為O(N)。

對于帶頭雙向循環(huán)鏈表,找尾是極其方便的,因為尾結點就在頭結點的前一個,可以一步就訪問到。所以,帶頭雙向循環(huán)鏈表的尾插與尾刪都為O(1)。

②頭插與頭刪的時間復雜度

兩種鏈表頭插與頭刪都為O(1)。對于鏈表這種數(shù)據(jù)結構而言,頭插與頭刪都是其優(yōu)勢。上一章中提到順序表的尾插與尾刪效率極高,但是頭插與頭刪卻比較劣勢。而鏈表正好相反,頭插與頭刪效率很高。因此面對不同的場景,要學會使用合適的數(shù)據(jù)結構。

③函數(shù)形參為何一個是二級指針,一個是一級指針?

單鏈表,我們需要對phead的值做修改。那么就得利用phead的指針。而phead本身就是一個指針,所以函數(shù)的形參為pphead的二級指針。

雙向循環(huán)鏈表,并不需要對phead做修改,而只是需要訪問它prev和next所指向的結點,所以只用一級指針即可。


完整源碼

無頭單向非循環(huán)鏈表

SList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

//申請一個結點
SLTNode* BuySLTNode(SLTDataType data);
//創(chuàng)建一個鏈表,包含數(shù)據(jù)為0~n
SLTNode* CreateSList(int n);
//釋放內(nèi)存
void SLTDestroy(SLTNode** pphead);
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType data);
//尾刪
void SLTPopBack(SLTNode** pphead);
//頭插
void SLTPushFront(SLTNode** pphead, SLTDataType data);
//頭刪
void SLTPopFront(SLTNode** pphead);
//查找data的結點
SLTNode* SLTFind(SLTNode** pphead, SLTDataType data);
//在pos位置前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType data);
//在pos位置后插入
void SLTInsertAfter(SLTNode* pos, SLTDataType data);
//刪除pos結點
void SLTErase(SLTNode** pphead, SLTNode* pos);
//打印鏈表內(nèi)容
void SLTPrint(SLTNode* phead);

SList.c

#define _CRT_SECURE_NO_DEPRECATE 1
#include"SList.h"

SLTNode* BuySLTNode(SLTDataType data)
{
	SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));
	//檢查是否申請成功
	if (newNode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	//對newNode進行初始化
	newNode->data = data;
	newNode->next = NULL;

	//返回申請成功的結點
	return newNode;
}

SLTNode* CreateSList(int n)
{
	SLTNode* phead = NULL;
	SLTNode* ptail = NULL;

	for (int i = 0; i < n; i++)
	{
		SLTNode* newNode = BuySLTNode(i);
		//若為第一個插入,則分情況處理
		if (phead == NULL)
		{
			phead = ptail = newNode;
		}
		else
		{
			ptail->next = newNode;
			ptail = newNode;
		}
	}
	return phead;
}

void SLTDestroy(SLTNode** pphead)
{
	assert(*pphead);
	SLTNode* cur = *pphead;
	//cur判斷何時結束
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

void SLTPushBack(SLTNode** pphead, SLTDataType data)
{
	SLTNode* newNode = BuySLTNode(data);
	//若為第一次插入,則分情況處理
	if (*pphead==NULL)
	{
		*pphead = newNode;
		return;
	}

	//找尾
	SLTNode* tail = *pphead;
	while(tail->next)
	{
		tail = tail->next;
	}
	//找到了,進行尾插
	tail->next = newNode;
}
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	//分情況處理
	if (*pphead == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}

	//找尾
	SLTNode* tail = *pphead;
	while (tail->next->next)
	{
		tail = tail->next;
	}
	//找到了,進行尾刪
	free(tail->next);
	tail->next = NULL;
}

void SLTPushFront(SLTNode** pphead, SLTDataType data)
{
	SLTNode* newNode = BuySLTNode(data);
	//進行頭插
	newNode->next = *pphead;
	*pphead = newNode;
}

void SLTPopFront(SLTNode** pphead)
{
	assert(*pphead);
	//進行頭刪
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

SLTNode* SLTFind(SLTNode** pphead, SLTDataType data)
{
	assert(*pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		//找到了,返回cur
		if (cur->data == data)
		{
			return cur;
		}
		cur = cur->next;
	}
	//沒找到,返回NULL
	return NULL;
}

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType data)
{
	assert(pos);
	SLTNode* newNode = BuySLTNode(data);
	//若pos恰好是phead,相當于進行頭插
	if (pos == *pphead)
	{
		SLTPushFront(pphead, data);
		return;
	}
	//找pos前一個指針
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	//找到了,進行插入
	prev->next = newNode;
	newNode->next = pos;
}

void SLTInsertAfter(SLTNode* pos, SLTDataType data)
{
	assert(pos);
	SLTNode* newNode = BuySLTNode(data);
	SLTNode* next = pos->next;
	pos->next = newNode;
	newNode->next = next;
}

void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	//若pos恰好就是phead,則相當于頭刪
	if (pos == *pphead)
	{
		SLTPopFront(pphead);
		return;
	}
	//找pos前一個結點
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	//找到了,進行刪除
	prev->next = pos->next;
	free(pos);
	pos = NULL;
}

void SLTPrint(SLTNode* phead)
{
	assert(phead);
	SLTNode* cur = phead;
	//cur控制何時結束
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

test.c

#define _CRT_SECURE_NO_DEPRECATE 1
#include"SList.h"

void test()
{
	SLTNode* phead = CreateSList(10);
	SLTPushBack(&phead, 0);
	SLTPushBack(&phead, 0);
	SLTPushBack(&phead, 0);
	SLTPushBack(&phead, 0);
	SLTPushBack(&phead, 0);
	SLTPrint(phead);

	SLTPushFront(&phead, 1);
	SLTPushFront(&phead, 1);
	SLTPushFront(&phead, 1);
	SLTPushFront(&phead, 1);
	SLTPushFront(&phead, 1);
	SLTPrint(phead);

	SLTNode* pos = SLTFind(&phead, 3);
	SLTInsert(&phead, pos, 300);
	SLTInsertAfter(pos, 30);
	SLTPrint(phead);
	SLTPopBack(&phead);
	SLTPopBack(&phead);
	SLTPopBack(&phead);
	SLTPopBack(&phead);
	SLTPopBack(&phead);

	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPopFront(&phead);
	SLTPrint(phead);
	SLTDestroy(&phead);
}
int main()
{
	test();
	return 0;
}

帶頭雙向循環(huán)鏈表

List.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int LTDataType;

typedef struct ListNode
{
	LTDataType data;
	struct ListNode* prev;//指向前一個結點
	struct ListNode* next;//指向后一個結點
}LTNode;

//申請一個結點
LTNode* BuyListNode(LTDataType data);
//初始化頭結點
LTNode* LTInit();
//釋放申請的內(nèi)存
void LTDestroy(LTNode* phead);
//尾插
void LTPushBack(LTNode* phead, LTDataType data);
//尾刪
void LTPopBack(LTNode* phead);
//頭插
void LTPushFront(LTNode* phead, LTDataType data);
//頭刪
void LTPopFront(LTNode* phead);
//查找data
LTNode* LTFind(LTNode* phead, LTDataType data);
//在pos位置前插入
void LTInsert(LTNode* phead, LTNode* pos, LTDataType data);
//刪除pos位置
void LTErase(LTNode* phead, LTNode* pos);
//判斷鏈表是否為空
bool LTEmpty(LTNode* phead);
//統(tǒng)計鏈表中數(shù)據(jù)的個數(shù)
size_t LTSize(LTNode* phead);
//打印鏈表存儲的數(shù)據(jù)
void LTPrint(LTNode* phead);

List.c

#define _CRT_SECURE_NO_DEPRECATE 1
#include"List.h"

LTNode* BuyListNode(LTDataType data)
{
	LTNode* newNode = (LTNode*)malloc(sizeof(LTNode));
	if (newNode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	newNode->data = data;
	newNode->prev = NULL;
	newNode->next = NULL;

	return newNode;
}

LTNode* LTInit()
{
	LTNode* phead = BuyListNode(-1);
	phead->prev = phead;
	phead->next = phead;
	return phead;
}

void LTDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}

	free(phead);
}

void LTPushBack(LTNode* phead, LTDataType data)
{
	assert(phead);
	LTNode* newNode = BuyListNode(data);
	LTNode* tail = phead->prev;

	newNode->next = phead;
	newNode->prev = tail;
	tail->next = newNode;
	phead->prev = newNode;
}

void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));
	LTNode* tail = phead->prev;
	tail->prev->next = phead;
	phead->prev = tail->prev;

	free(tail);
}

void LTPushFront(LTNode* phead, LTDataType data)
{
	assert(phead);
	LTNode* newNode = BuyListNode(data);
	
	newNode->next = phead->next;
	phead->next->prev = newNode;

	phead->next = newNode;
	newNode->prev = phead;
}

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(!LTEmpty(phead));
	LTNode* cur = phead->next;
	phead->next = cur->next;
	cur->next->prev = phead;

	free(cur);
}

LTNode* LTFind(LTNode* phead, LTDataType data)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data==data)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

void LTInsert(LTNode* phead, LTNode* pos, LTDataType data)
{
	assert(phead);
	LTNode* newNode = BuyListNode(data);
	pos->prev->next = newNode;
	newNode->prev = pos->prev;

	newNode->next = pos;
	pos->prev = newNode;
}

void LTErase(LTNode* phead,LTNode* pos)
{
	assert(phead);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;

	free(pos);
}

bool LTEmpty(LTNode* phead)
{
	assert(phead);
	if (phead->next == phead)
	{
		return true;
	}
	return false;
}

size_t LTSize(LTNode* phead)
{
	assert(phead);
	size_t size = 0;
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		size++;
		cur = cur->next;
	}
	return size;
}

void LTPrint(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

test.c

#define _CRT_SECURE_NO_DEPRECATE 1
#include"List.h"

void test()
{
	LTNode* phead = LTInit();
	LTPushBack(phead, 2);
	LTPushBack(phead, 1);
	LTPushBack(phead, 1);
	LTPushBack(phead, 1);
	LTPushBack(phead, 1);
	LTPushBack(phead, 1);
	LTPushFront(phead, 0);
	LTPushFront(phead, 0);
	LTPushFront(phead, 0);
	LTPushFront(phead, 0);
	LTPushFront(phead, 0);
	LTPrint(phead);
	LTPopFront(phead);
	LTPopFront(phead);
	LTPopFront(phead);
	LTPrint(phead);
	LTPopBack(phead);
	LTPopBack(phead);
	LTPopBack(phead);
	LTPrint(phead);
	LTNode* pos = LTFind(phead, 2);
	LTInsert(phead, pos, 200);
	LTInsert(phead, pos, 200);
	LTInsert(phead, pos, 200);
	LTPrint(phead);
	LTErase(phead, pos);
	LTPrint(phead);
	LTDestroy(phead);
}

int main()
{
	test();
	return 0;
}

鏈表源碼,新星計劃免費學習專欄·數(shù)據(jù)結構與算法,數(shù)據(jù)結構,鏈表,c語言

?

到了這里,關于『初階數(shù)據(jù)結構 ? C語言』⑨ - 基于結點的數(shù)據(jù)結構——鏈表(單鏈表&&雙向循環(huán)鏈表)附完整源碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關文章

  • 【數(shù)據(jù)結構和算法初階(C語言)】復雜鏈表(隨機指針,隨機鏈表的復制)題目詳解+鏈表順序表結尾

    【數(shù)據(jù)結構和算法初階(C語言)】復雜鏈表(隨機指針,隨機鏈表的復制)題目詳解+鏈表順序表結尾

    目錄 ?1.隨機鏈表的復制 1.2題目描述? 1.3題目分析 1.4解題: 2.順序表和鏈表對比 2.1cpu高速緩存利用率 3.結語 一個長度為? n ?的鏈表,每個節(jié)點包含一個額外增加的隨機指針? random ? 該指針可以指向鏈表中的任何節(jié)點或空節(jié)點。? ? ? ? 構造這個鏈表的? 深拷貝 。?深拷貝

    2024年03月10日
    瀏覽(93)
  • 【數(shù)據(jù)結構初階】三、 線性表里的鏈表(無頭+單向+非循環(huán)鏈表 -- C語言實現(xiàn))

    【數(shù)據(jù)結構初階】三、 線性表里的鏈表(無頭+單向+非循環(huán)鏈表 -- C語言實現(xiàn))

    ========================================================================= 相關代碼gitee自取 : C語言學習日記: 加油努力 (gitee.com) ?========================================================================= 接上期 : 【數(shù)據(jù)結構初階】二、 線性表里的順序表(C語言實現(xiàn)順序表)-CSDN博客 ?=========================

    2024年02月08日
    瀏覽(33)
  • 【數(shù)據(jù)結構OJ題】鏈表中倒數(shù)第k個結點

    【數(shù)據(jù)結構OJ題】鏈表中倒數(shù)第k個結點

    原題鏈接:https://www.nowcoder.com/practice/529d3ae5a407492994ad2a246518148a?tpId=13tqId=11167rp=2ru=/activity/ojqru=/ta/coding-interviews/question-ranking 目錄 1. 題目描述 2. 思路分析 3. 代碼實現(xiàn) 快慢指針法 ? (如果有小伙伴不了解快慢指針法,可以看看這篇文章:https://blog.csdn.net/m0_62531913/article/details/

    2024年02月12日
    瀏覽(31)
  • 初階數(shù)據(jù)結構:鏈表

    初階數(shù)據(jù)結構:鏈表

    經(jīng)過學習與練習,已經(jīng)掌握了順序表的相關知識并且能夠自我實現(xiàn)。在這一過程中,通過對其結構的實現(xiàn),發(fā)現(xiàn)順序表的尾部插入刪除數(shù)據(jù)效率很高,可是,在 頭部與隨機插入的場景下效率低下 而且 存在擴容消耗 等一些問題。而有這樣一種數(shù)據(jù)結構可以很好的解決順序表存

    2024年01月20日
    瀏覽(86)
  • 【數(shù)據(jù)結構】鏈表OJ面試題(《刪除定值、反轉(zhuǎn)、返回中間結點、倒數(shù)第k節(jié)點、合并鏈表》)+解析)

    【數(shù)據(jù)結構】鏈表OJ面試題(《刪除定值、反轉(zhuǎn)、返回中間結點、倒數(shù)第k節(jié)點、合并鏈表》)+解析)

    還不清楚鏈表的碼喵們可以看看前篇關于鏈表的詳解 既然已經(jīng)懂得了鏈表該如何實現(xiàn),那么現(xiàn)在就趁熱打鐵開始練習!這里給碼喵們整理了相對不錯的一些OJ題來練習 ?力扣(LeetCode)官網(wǎng) - 全球極客摯愛的技術成長平臺 思路:遍歷整個表,訪問每個表的值并且刪除再將nex

    2024年02月22日
    瀏覽(20)
  • 初階數(shù)據(jù)結構(三)鏈表

    初階數(shù)據(jù)結構(三)鏈表

    ??博主csdn個人主頁:小小unicorn?? ?專欄分類:c++ ??代碼倉庫:小小unicorn的學習足跡?? ??????關注我?guī)銓W習編程知識 前面我們講的線性表的 順序存儲結構 。它是有缺點的,最大的缺點就是插入和刪除時需要移動大量元素,這顯然就需要 耗費時間 ,那能不能想辦法

    2024年02月09日
    瀏覽(94)
  • 【數(shù)據(jù)結構初階】鏈表OJ

    【數(shù)據(jù)結構初階】鏈表OJ

    OJ 方案一: 題目解析: 方案二: 題目解析:把原鏈表遍歷一遍,插入新鏈表 OJ 題目解析: OJ 題目解析: OJ 題目解析: OJ 題目解析: OJ 題目解析: OJ 題目解析: OJ 題目解析: 定義快慢指針,使快指針先走與慢指針同步。然后同時走看是否相交 OJ 題目解析: OJ 題目解析:

    2024年02月05日
    瀏覽(94)
  • 初階數(shù)據(jù)結構之---二叉樹鏈式結構(二叉樹的構建,二叉樹的前序,中序,后序和層序遍歷,計算二叉樹結點個數(shù),第k層結點個數(shù),葉子結點個數(shù),判斷是否為完全二叉樹)

    初階數(shù)據(jù)結構之---二叉樹鏈式結構(二叉樹的構建,二叉樹的前序,中序,后序和層序遍歷,計算二叉樹結點個數(shù),第k層結點個數(shù),葉子結點個數(shù),判斷是否為完全二叉樹)

    本篇博客是初階數(shù)據(jù)結構樹的收尾,將會講掉 基本二叉樹鏈式結構的具體內(nèi)容和實現(xiàn),包括二叉樹的構建,前序遍歷,中序遍歷,后序遍歷和層序遍歷,計算二叉樹結點個數(shù),第k層結點個數(shù),二叉樹葉子結點個數(shù),以及判斷一個二叉樹是否為完全二叉樹 。話不多說,開始我

    2024年03月24日
    瀏覽(27)
  • 【數(shù)據(jù)結構初階】第四節(jié).鏈表詳講

    【數(shù)據(jù)結構初階】第四節(jié).鏈表詳講

    前言 一、單鏈表的概念 二、鏈表的創(chuàng)建 2.1鏈表的初始化 2.2 打印鏈表 2.3 獲取鏈表的長度 2.4?判斷鏈表是否為空 三、新增結點 3.1頭插 3.2?指定下標插入 四、刪除結點 4.1 頭刪 4.2 指定下標的刪除 4.3?刪除鏈表中的指定元素 五、單鏈表查找 六、附錄 總代碼 測試代碼 總結 前

    2023年04月15日
    瀏覽(16)
  • 貪吃蛇項目(基于C語言和數(shù)據(jù)結構中的鏈表)

    貪吃蛇項目(基于C語言和數(shù)據(jù)結構中的鏈表)

    首先先建立3個文件。 Snake.h 函數(shù)的聲明 Snake.c 函數(shù)的定義 Test.c? ? ?貪吃蛇的測試? ? 我們分析這整個項目 首先在我們實現(xiàn)游戲開始的部分之前,我們要先創(chuàng)建貪吃蛇的節(jié)點,再由此創(chuàng)建整個貪吃蛇所包含的一些信息: 我們枚舉一下這個貪吃蛇中所有的一些狀態(tài): 然后我們

    2024年02月20日
    瀏覽(26)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領取紅包

二維碼2

領紅包