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

【數(shù)據(jù)結(jié)構(gòu)】單鏈表 && 雙鏈表(鏈?zhǔn)胶蛿?shù)組實(shí)現(xiàn))

這篇具有很好參考價(jià)值的文章主要介紹了【數(shù)據(jù)結(jié)構(gòu)】單鏈表 && 雙鏈表(鏈?zhǔn)胶蛿?shù)組實(shí)現(xiàn))。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

??? ??????? 歡迎來到小林的博客?。?br> ?????????博客主頁:??小林愛敲代碼
?????????博客專欄:?? 數(shù)據(jù)結(jié)構(gòu)與算法
?????????社區(qū) :?? 進(jìn)步學(xué)堂
?????????歡迎關(guān)注:??點(diǎn)贊??收藏??留言

前言

今天給大家?guī)硭膫€(gè)內(nèi)容,一個(gè)是單鏈表非帶頭的實(shí)現(xiàn),一個(gè)是雙鏈表帶頭循環(huán)的實(shí)現(xiàn)。剩下的就是數(shù)組模擬單鏈表和雙鏈表。

單鏈表

鏈表,在內(nèi)存中并不是連續(xù)存儲(chǔ)的。而鏈表通常會(huì)有next指針指向它的下一個(gè)節(jié)點(diǎn)。鏈表的最后一個(gè)節(jié)點(diǎn)一定指向空。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

頭插

頭插我們需要讓新節(jié)點(diǎn)指向頭節(jié)點(diǎn),然后更換頭節(jié)點(diǎn)為新節(jié)點(diǎn)即可。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

尾插

我們只需要找到最后一個(gè)節(jié)點(diǎn),讓它的next指向新節(jié)點(diǎn),再把新節(jié)點(diǎn)指向NULL即可。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

頭刪

先保存頭節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),然后刪除頭節(jié)點(diǎn)。并把保存下來的下一個(gè)節(jié)點(diǎn)設(shè)置為新的頭節(jié)點(diǎn)。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

尾刪

尾刪需要記錄一下最后一個(gè)節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)。然后刪除最后一個(gè)節(jié)點(diǎn),把前一個(gè)節(jié)點(diǎn)指向NULL。否則會(huì)出現(xiàn)指向野指針的情況。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

指定位置后插入

我們這里只講解在指定位置的后一個(gè)元素插入,因?yàn)閱捂湵碓谥付ü?jié)點(diǎn)的前一個(gè)插入,需要前一個(gè)節(jié)點(diǎn)。但是單鏈表只指后不指前。所以想拿到前一個(gè)節(jié)點(diǎn)必須再遍歷一次,所以不建議單鏈表用前插。在指定位置后插,我們只需要保存一下這個(gè)位置的下一個(gè)節(jié)點(diǎn),然后讓新節(jié)點(diǎn)指向這個(gè)位置的下一個(gè)節(jié)點(diǎn)。這個(gè)位置指向新節(jié)點(diǎn)。

假設(shè)我們?cè)趐os位置后面插入:

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

指定位置后刪除

我們還是刪除指定位置后的元素,因?yàn)槿绻麆h除指定元素,我們也需要它的前一個(gè)節(jié)點(diǎn)。單鏈表無法直接獲取前一個(gè)節(jié)點(diǎn)。指定位置后刪除,我們只需要保存下一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),然后刪除下一個(gè)節(jié)點(diǎn),然后讓這個(gè)位置指向保存下來的的節(jié)點(diǎn)。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

單鏈表的代碼實(shí)現(xiàn):

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

typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;
}SListNode;


// 動(dòng)態(tài)申請(qǐng)一個(gè)節(jié)點(diǎn)
SListNode* BuySListNode(SLTDateType x)
{
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode)); //開辟空間
	newNode->data = x; //空間值為x
	return newNode;
}
// 單鏈表打印
void SListPrint(SListNode* plist)
{
	SListNode* cur = plist;
	while (cur) //遍歷一遍鏈表
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
// 單鏈表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{
	assert(pplist);
	if (*pplist == NULL)//如果鏈表為空調(diào)用頭插
	{
		SListPushFront(pplist, x); 
		return;
	}
    //找到尾部節(jié)點(diǎn)
	SListNode* tail = *pplist;
	while (tail->next)
	{
		tail = tail->next;
	}
    //復(fù)用SListInsertAfter函數(shù)插入
	SListInsertAfter(tail, x);
}
// 單鏈表的頭插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
	assert(pplist);
	SListNode* newNode = BuySListNode(x);
	if (*pplist == NULL) //鏈表為空需要更新頭節(jié)點(diǎn)
	{
		*pplist = newNode;
		newNode->next = NULL;
		return;
	}
	newNode->next = *pplist;
	*pplist = newNode;
}
// 單鏈表的尾刪
void SListPopBack(SListNode** pplist)
{
	assert(pplist && *pplist);
	if ((*pplist)->next == NULL) //鏈表就一個(gè)元素,調(diào)用頭刪
	{
		SListPopFront(pplist);
		return;
	}
	SListNode* tail = *pplist;
	SListNode* prev = NULL;
	
    //遍歷鏈表并刪除
	while (tail->next)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}
// 單鏈表頭刪
void SListPopFront(SListNode** pplist)
{
	assert(pplist && *pplist);
    //頭刪
	SListNode* next = (*pplist)->next;
	free(*pplist);
	*pplist = next;
}
// 單鏈表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
	SListNode* cur = plist;
	while (cur)
	{
		if (x == cur->data)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
// 單鏈表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
	assert(pos);
	SListNode* next = pos->next;
	SListNode* newNode = BuySListNode(x);
	pos->next = newNode;
	newNode->next = next;
}
// 單鏈表刪除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{
	assert(pos);
	SListNode* nextnext = pos->next->next;
	free(pos->next);
	pos->next = nextnext;
}
// 單鏈表的銷毀
void SListDestroy(SListNode* plist)
{
	SListNode* cur = plist;
	SListNode* next = plist->next;
	while (cur)
	{
		next = cur->next;
		free(cur);
		cur = next;
	}
}

雙鏈表

這里我們實(shí)現(xiàn)一個(gè)帶頭循環(huán)的雙鏈表,因?yàn)檠h(huán)鏈表可以從頭節(jié)點(diǎn)直接找到最后一個(gè)節(jié)點(diǎn)。帶頭是因?yàn)楦玫拇_定鏈表的尾部,帶頭節(jié)點(diǎn)在這里就沖當(dāng)了尾節(jié)點(diǎn)的作用。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

指定位置前插入

雙鏈表我們只需要寫指定插入和指定刪除,就可以復(fù)用這兩個(gè)接口實(shí)現(xiàn)頭插,頭刪,尾插,尾刪了。指定位置前插入和單鏈表類似。先保存前一個(gè)節(jié)點(diǎn)坐標(biāo),然后讓前一個(gè)節(jié)點(diǎn)和新節(jié)點(diǎn)連接,再把自己的prev指針指向新節(jié)點(diǎn)。

為了方便觀看,我把首尾節(jié)點(diǎn)指向的線省略了,實(shí)際上指針是指向首尾的。我們?cè)趐os前插入一個(gè)節(jié)點(diǎn)。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

動(dòng)圖演示可能線連接的不怎么好看,但最后都是這樣的

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

指定位置刪除

指定位置刪除,我們只需要存下前一個(gè)節(jié)點(diǎn)和后一個(gè)節(jié)點(diǎn)。然后把兩個(gè)節(jié)點(diǎn)連接起來,再釋放當(dāng)前節(jié)點(diǎn)即可。

數(shù)組雙鏈表,數(shù)據(jù)結(jié)構(gòu)與算法,數(shù)據(jù)結(jié)構(gòu),鏈表

雙鏈表代碼實(shí)現(xiàn):

#include <assert.h>
#include<stdio.h>

// 帶頭+雙向+循環(huán)鏈表增刪查改實(shí)現(xiàn)
typedef int LTDataType;

typedef struct _ListNode
{
	LTDataType _data;
	struct _ListNode* _next; //指向后一個(gè)節(jié)點(diǎn)
	struct _ListNode* _prev; //指向前一個(gè)節(jié)點(diǎn)
}ListNode;



//創(chuàng)建節(jié)點(diǎn)
ListNode* CreateListNode(LTDataType x)
{
	ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
	newNode->_data = x;
	return newNode;
}

// 創(chuàng)建鏈表,返回鏈表的頭結(jié)點(diǎn).
ListNode* ListCreate()
{
	ListNode* head = CreateListNode(0);
	head->_next = head; //自己指向自己
	head->_prev = head; //自己指向自己
	return head;
}

// 雙向鏈表銷毀
void ListDestory(ListNode* pHead)
{
	ListNode* cur = pHead->_next;
	while (cur != pHead)
	{
		ListNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	free(pHead);
}
// 雙向鏈表打印
void ListPrint(ListNode* pHead)
{
	ListNode* cur = pHead->_next;
	while(cur != pHead)
	{
		printf("%d->", cur->_data);
		cur = cur->_next;
	}
	printf("NULL\n");
}
// 雙向鏈表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
	ListInsert(pHead, x); //復(fù)用指定插入
}
// 雙向鏈表尾刪
void ListPopBack(ListNode* pHead)
{
	ListErase(pHead->_prev); //復(fù)用指定刪除
}
// 雙向鏈表頭插
void ListPushFront(ListNode* pHead, LTDataType x)
{
	ListInsert(pHead->_next, x); //復(fù)用指定插入
}
// 雙向鏈表頭刪
void ListPopFront(ListNode* pHead)
{
	ListErase(pHead->_next); //復(fù)用指定刪除
}
// 雙向鏈表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
	while (pHead)
	{
		if (pHead->_data == x)
			return pHead;
		pHead = pHead->_next;
	}
	return NULL;
}
// 雙向鏈表在pos的前面進(jìn)行插入
void ListInsert(ListNode* pos, LTDataType x)
{
	ListNode* prev = pos->_prev;
	ListNode* newNode = CreateListNode(x);
	prev->_next = newNode;
	newNode->_prev = prev;
	newNode->_next = pos;
	pos->_prev = newNode;
}
// 雙向鏈表刪除pos位置的節(jié)點(diǎn)
void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* prev = pos->_prev;
	ListNode* next = pos->_next;
	free(pos);
	prev->_next = next;
	next->_prev = prev;
}

數(shù)組模擬單鏈表

數(shù)組模擬鏈表我們需要開一個(gè)數(shù)組來存鏈表的值,還要開一個(gè)數(shù)組連存儲(chǔ)鏈表的指向,還需要一個(gè)變量來代表鏈表的編號(hào)。

e[] 數(shù)組用來存儲(chǔ)鏈表的值 , ne[] 數(shù)組用來存儲(chǔ)節(jié)點(diǎn)指向節(jié)點(diǎn)的下標(biāo),數(shù)組的下標(biāo)代表節(jié)點(diǎn)。 head代表頭節(jié)點(diǎn),值-1則為空節(jié)點(diǎn)。 idx 是給鏈表的節(jié)點(diǎn)的一個(gè)編號(hào),代表下標(biāo)。

代碼:

#include<iostream>
using namespace std;

const int N = 100010; //鏈表總大小
int e[N];//存儲(chǔ)值
int ne[N];//存儲(chǔ)下一個(gè)節(jié)點(diǎn) 
int head,idx;  

//鏈表初始化
void init()
{
    head = -1 ; //-1為空
    idx = 0; //當(dāng)前節(jié)點(diǎn)的編號(hào)
}
void add_to_head(int x)  //頭插
{
    e[idx] = x; //給新節(jié)點(diǎn)賦值
    ne[idx] = head; //指向head指向的節(jié)點(diǎn)
    head = idx++; //頭節(jié)點(diǎn)指向新節(jié)點(diǎn)
}

//插入到k節(jié)點(diǎn)后面
void add(int k ,int x)
{
    e[idx] = x; //idx編號(hào)的元素的值賦值為x
    ne[idx] = ne[k]; //指向k節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)
    ne[k] = idx++; //指向新插入節(jié)點(diǎn)
}

void remove(int k )
{
    ne[k] = ne[ne[k]]; //指向下一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)
}

數(shù)組模擬雙鏈表

單鏈表需要一個(gè)數(shù)組來存儲(chǔ)指向的節(jié)點(diǎn),那么雙鏈表就需要兩個(gè)數(shù)組來存儲(chǔ),一個(gè)指向前節(jié)點(diǎn),一個(gè)指向后節(jié)點(diǎn)。

r[] 存儲(chǔ)節(jié)點(diǎn)的后一個(gè)節(jié)點(diǎn)下標(biāo)

l[] 存儲(chǔ)節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)下標(biāo)

e[] 存儲(chǔ)節(jié)點(diǎn)的值

hh 頭的下標(biāo)

tt 尾的下標(biāo)

idx 節(jié)點(diǎn)的編號(hào),對(duì)應(yīng)數(shù)組下標(biāo),每一個(gè)新的編號(hào)被使用說明創(chuàng)建了一個(gè)節(jié)點(diǎn)

#include<iostream>
#include<string>
using namespace std;

const int N = 1e6 + 10;
int r[N],l[N],e[N];
int hh,tt,idx;

void init()
{
    hh = 0,tt = 1,idx = 2;//hh代表頭,tt代表尾,idx是其他節(jié)點(diǎn)的編號(hào)
    r[hh] = tt; //頭指向尾
    l[tt] = hh; //尾指向頭
}

//指定位置的右邊插入
void add_right(int k,int x)
{
    e[idx] = x; //idx編號(hào)的節(jié)點(diǎn)的值為x
    r[idx] = r[k],l[idx] = k; //idx右邊指向k的右邊,坐標(biāo)指向k
    l[r[k]] = idx,r[k] = idx++; //k右節(jié)點(diǎn)的坐標(biāo)指向idx,k的右邊指向idx。idx編號(hào)+1
}
//刪除
void remove(int k)
{
    r[l[k]] = r[k]; //k前一個(gè)節(jié)點(diǎn)的右一個(gè)節(jié)點(diǎn)指向k的右節(jié)點(diǎn)
    l[r[k]] = l[k]; //k后一個(gè)節(jié)點(diǎn)的左節(jié)點(diǎn)指向k的左節(jié)點(diǎn)
}

總結(jié):

鏈?zhǔn)綄?shí)現(xiàn)的鏈表的動(dòng)態(tài)的,每次增加節(jié)點(diǎn)需要開辟空間。開辟空間是有消耗的。而數(shù)組模擬的鏈表是靜態(tài)的,這就意味著數(shù)組模擬的鏈表比鏈?zhǔn)綄?shí)現(xiàn)的鏈表更快。但因?yàn)槭庆o態(tài)的,會(huì)占用固定的空間。所以個(gè)人推薦,做題的時(shí)候用靜態(tài)鏈表,其他的時(shí)候用動(dòng)態(tài)鏈表。文章來源地址http://www.zghlxwxcb.cn/news/detail-790247.html

到了這里,關(guān)于【數(shù)據(jù)結(jié)構(gòu)】單鏈表 && 雙鏈表(鏈?zhǔn)胶蛿?shù)組實(shí)現(xiàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包