欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)邀請(qǐng)碼778899分享:【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表

柚子快報(bào)邀請(qǐng)碼778899分享:【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表

http://yzkb.51969.com/

Hi~!這里是奮斗的小羊,很榮幸您能閱讀我的文章,誠(chéng)請(qǐng)?jiān)u論指點(diǎn),歡迎歡迎 ~~ ??個(gè)人主頁(yè):奮斗的小羊 ??所屬專欄:數(shù)據(jù)結(jié)構(gòu)

?本系列文章為個(gè)人學(xué)習(xí)筆記,在這里撰寫(xiě)成文一為鞏固知識(shí),二為記錄我的學(xué)習(xí)過(guò)程及理解。文筆、排版拙劣,望見(jiàn)諒。

目錄

前言1、鏈表的分類2、雙向鏈表的實(shí)現(xiàn)2.1雙向鏈表節(jié)點(diǎn)2.2申請(qǐng)節(jié)點(diǎn)2.3數(shù)據(jù)的打印和查找2.4頭插和尾插2.5頭刪和尾刪2.6在指定位置插入、刪除數(shù)據(jù)2.7銷毀雙向鏈表

3、雙向鏈表完整代碼4、順序表和鏈表比較總結(jié)

前言

單鏈表只能通過(guò)某個(gè)節(jié)點(diǎn)的地址單向的訪問(wèn)數(shù)據(jù),而雙向鏈表可以通過(guò)某個(gè)節(jié)點(diǎn)的地址雙向的訪問(wèn)數(shù)據(jù),增刪查改的效率更高,但是代碼的實(shí)現(xiàn)卻比單鏈表簡(jiǎn)單,總的來(lái)說(shuō),雙向鏈表優(yōu)勢(shì)更明顯一些。

1、鏈表的分類

鏈表分為帶頭的、不帶頭的,單向的、雙向的,循環(huán)的、不循環(huán)的組合起來(lái)一共八種,而我們只學(xué)習(xí)常見(jiàn)的不帶頭單向不循環(huán)鏈表和帶頭雙向循環(huán)鏈表,也就是單鏈表和雙向鏈表。 雙向鏈表: 其實(shí)在上篇文章中我們將單鏈表的第一個(gè)節(jié)點(diǎn)稱作頭節(jié)點(diǎn)是不準(zhǔn)確的,之所以這么稱呼是為了好理解,因?yàn)閱捂湵硎遣粠ь^的,雙向鏈表才有頭結(jié)點(diǎn),也稱作哨兵位。

雙向鏈表頭節(jié)點(diǎn)內(nèi)不存有效數(shù)據(jù),存的是無(wú)效的數(shù)據(jù)。哨兵位是不能改變的,只能改變其指向

2、雙向鏈表的實(shí)現(xiàn)

2.1雙向鏈表節(jié)點(diǎn)

雙向鏈表的節(jié)點(diǎn)需要存數(shù)據(jù),還要存前一個(gè)和后一個(gè)節(jié)點(diǎn)的地址,因此雙向鏈表的節(jié)點(diǎn)為:

typedef int dlist_data_type;

//雙向鏈表節(jié)點(diǎn)

typedef struct dlist

{

dlist_data_type data;

struct dlist* next

struct dlist* prev;

}dlist;

2.2申請(qǐng)節(jié)點(diǎn)

不像單鏈表,雙向鏈表最少得有一個(gè)節(jié)點(diǎn),就是頭節(jié)點(diǎn),也叫哨兵位。 在增刪查改之前,雙向鏈表必須初始化一個(gè)哨兵位,哨兵位內(nèi)存一個(gè)無(wú)效數(shù)據(jù)。

申請(qǐng)的節(jié)點(diǎn)初始時(shí)兩個(gè)指針指向自己。

//申請(qǐng)節(jié)點(diǎn)

dlist* dlist_buy(dlist_data_type x)

{

dlist* newdlist = (dlist*)malloc(sizeof(dlist));

if (newdlist == NULL)

{

perror("malloc fail!");

return 1;

}

newdlist->data = x;

newdlist->next = newdlist;

newdlist->prev = newdlist;

return newdlist;

}

初始化哨兵位有以下兩種方法: 以參數(shù)的形式返回:

void dlist_init(dlist** pphead)

{

assert(pphead);

*pphead = dlist_buy(-1);

}

這個(gè)方法要求使用二級(jí)指針。 以返回值的形式返回:

dlist* dlist_init()

{

dlist* phead = dlist_buy(-1);

return phead;

}

這個(gè)方法更加簡(jiǎn)單易理解。

2.3數(shù)據(jù)的打印和查找

數(shù)據(jù)的打印和查找跟單鏈表區(qū)別不大,就不再贅述了。 唯一需要注意的是結(jié)束循環(huán)的條件,當(dāng)指針指向哨兵位時(shí)結(jié)束循環(huán),而不是判NULL。

//打印數(shù)據(jù)

void dlist_print(dlist* phead)

{

assert(phead);

dlist* pcur = phead->next;

while (pcur != phead)

{

printf("%d->", pcur->data);

pcur = pcur->next;

}

printf("NULL\n");

}

//查找

dlist* dlist_find(dlist* phead, dlist_data_type x)

{

assert(phead);

dlist* pcur = phead->next;

while (pcur != phead)

{

if (pcur->data == x)

{

return pcur;

}

pcur = pcur->next;

}

return NULL;

}

2.4頭插和尾插

與單鏈表不同的是,雙向鏈表的增刪查改操作不會(huì)改變哨兵位,因此只需要傳值調(diào)用就可。 雙向鏈表的插入操作需要對(duì)三個(gè)節(jié)點(diǎn)做修改,在修改的過(guò)程中,注意先修改新節(jié)點(diǎn),再修改后一個(gè)節(jié)點(diǎn),最后修改前一個(gè)節(jié)點(diǎn)。

//插入操作不改變哨兵位,因此傳一級(jí)指針即可

//尾插

void dlist_push_back(dlist* phead, dlist_data_type x)

{

assert(phead);

dlist* newdlist = dlist_buy(x);

//新尾節(jié)點(diǎn)

newdlist->prev = phead->prev;

newdlist->next = phead;

//舊尾節(jié)點(diǎn)

phead->prev->next = newdlist;

//頭節(jié)點(diǎn)(哨兵位)

phead->prev = newdlist;

}

//頭插

void dlist_push_front(dlist* phead, dlist_data_type x)

{

assert(phead);

dlist* newdlist = dlist_buy(x);

//新節(jié)點(diǎn)

newdlist->prev = phead;

newdlist->next = phead->next;

//舊節(jié)點(diǎn)

phead->next->prev = newdlist;

//哨兵位

phead->next = newdlist;

}

2.5頭刪和尾刪

刪除操作的前提是不能沒(méi)有節(jié)點(diǎn)(哨兵位不算),在刪除前還是先保存節(jié)點(diǎn)的地址,將雙向鏈表重新拼接起來(lái)后再釋放節(jié)點(diǎn)。

//尾刪

void dlist_pop_back(dlist* phead)

{

assert(phead);

assert(phead->next != phead);//雙向鏈表不能為空

dlist* del = phead->prev;

//新尾節(jié)點(diǎn)

del->prev->next = phead;

//哨兵位

phead->prev = del->prev;

free(del);

del = NULL;

}

//頭刪

void dlist_pop_front(dlist* phead)

{

assert(phead);

assert(phead->next != phead);

dlist* del = phead->next;

del->next->prev = phead;

phead->next = del->next;

free(del);

del = NULL;

}

2.6在指定位置插入、刪除數(shù)據(jù)

//在指定位置之后插入數(shù)據(jù)

void dlist_insert_back(dlist* pos, dlist_data_type x)

{

assert(pos);

dlist* newdlist = dlist_buy(x);

newdlist->prev = pos;

newdlist->next = pos->next;

pos->next->prev = newdlist;

pos->next = newdlist;

}

//刪除指定位置的節(jié)點(diǎn)

void dlist_erase(dlist* pos)

{

assert(pos);

dlist* del = pos;

pos->prev->next = pos->next;

pos->next->prev = pos->prev;

free(pos);

pos = NULL;

}

刪除指定位置的數(shù)據(jù)后,因?yàn)檫@個(gè)函數(shù)我們用的是傳值調(diào)用,在釋放掉指定位置的節(jié)點(diǎn)后,只是把形參指針置NULL,而實(shí)參指針依舊指向這個(gè)位置,因此在函數(shù)調(diào)用結(jié)束后要給實(shí)參指針置NULL。

2.7銷毀雙向鏈表

雙向鏈表銷毀的結(jié)束條件也是當(dāng)遍歷指針指向頭節(jié)點(diǎn)時(shí)跳出循環(huán),最后還要單獨(dú)釋放哨兵位,雙向鏈表的銷毀函數(shù)調(diào)用結(jié)束后,也要給指向哨兵位的指針置NULL。

//銷毀

void dlist_destroy(dlist* phead)

{

assert(phead);

dlist* pcur = phead->next;

while (pcur != phead)

{

dlist* next = pcur->next;

free(pcur);

pcur = next;

}

free(pcur);

pcur = NULL;

}

3、雙向鏈表完整代碼

dlist.h:

#pragma once

#include

#include

#include

typedef int dlist_data_type;

//雙向鏈表節(jié)點(diǎn)

typedef struct dlist

{

dlist_data_type data;

struct dlist* next;

struct dlist* prev;

}dlist;

//初始化

//插入數(shù)據(jù)之前,雙向鏈表必須初始化到只有一個(gè)頭節(jié)點(diǎn)(哨兵位)

//void dlist_init(dlist** pphead);//以參數(shù)的形式返回

dlist* dlist_init();//以返回值的形式返回

//打印數(shù)據(jù)

void dlist_print(dlist* phead);

//查找

dlist* dlist_find(dlist* phead, dlist_data_type x);

//尾插

void dlist_push_back(dlist* phead, dlist_data_type x);

//頭插

void dlist_push_front(dlist* phead, dlist_data_type x);

//尾刪

void dlist_pop_back(dlist* phead);

//頭刪

void dlist_pop_front(dlist* phead);

//在指定位置之后插入數(shù)據(jù)

void dlist_insert_back(dlist* pos, dlist_data_type x);

//刪除指定位置的節(jié)點(diǎn)

void dlist_erase(dlist* pos);

//銷毀

void dlist_destroy(dlist* phead);

dlist.c:

#define _CRT_SECURE_NO_WARNINGS

#include "dlist.h"

//申請(qǐng)節(jié)點(diǎn)

dlist* dlist_buy(dlist_data_type x)

{

dlist* newdlist = (dlist*)malloc(sizeof(dlist));

if (newdlist == NULL)

{

perror("malloc fail!");

return 1;

}

newdlist->data = x;

newdlist->next = newdlist;

newdlist->prev = newdlist;

return newdlist;

}

//初始化

//void dlist_init(dlist** pphead)

//{

// assert(pphead);

// *pphead = dlist_buy(-1);

//}

dlist* dlist_init()

{

dlist* phead = dlist_buy(-1);

return phead;

}

//打印數(shù)據(jù)

void dlist_print(dlist* phead)

{

assert(phead);

dlist* pcur = phead->next;

while (pcur != phead)

{

printf("%d->", pcur->data);

pcur = pcur->next;

}

printf("NULL\n");

}

//查找

dlist* dlist_find(dlist* phead, dlist_data_type x)

{

assert(phead);

dlist* pcur = phead->next;

while (pcur != phead)

{

if (pcur->data == x)

{

return pcur;

}

pcur = pcur->next;

}

return NULL;

}

//插入操作不改變哨兵位,因此傳一級(jí)指針即可

//尾插

void dlist_push_back(dlist* phead, dlist_data_type x)

{

assert(phead);

dlist* newdlist = dlist_buy(x);

//新尾節(jié)點(diǎn)

newdlist->prev = phead->prev;

newdlist->next = phead;

//舊尾節(jié)點(diǎn)

phead->prev->next = newdlist;

//頭節(jié)點(diǎn)(哨兵位)

phead->prev = newdlist;

}

//頭插

void dlist_push_front(dlist* phead, dlist_data_type x)

{

assert(phead);

dlist* newdlist = dlist_buy(x);

//新節(jié)點(diǎn)

newdlist->prev = phead;

newdlist->next = phead->next;

//舊節(jié)點(diǎn)

phead->next->prev = newdlist;

//哨兵位

phead->next = newdlist;

}

//尾刪

void dlist_pop_back(dlist* phead)

{

assert(phead);

assert(phead->next != phead);//雙向鏈表不能為空

dlist* del = phead->prev;

//新尾節(jié)點(diǎn)

del->prev->next = phead;

//哨兵位

phead->prev = del->prev;

free(del);

del = NULL;

}

//頭刪

void dlist_pop_front(dlist* phead)

{

assert(phead);

assert(phead->next != phead);

dlist* del = phead->next;

del->next->prev = phead;

phead->next = del->next;

free(del);

del = NULL;

}

//在指定位置之后插入數(shù)據(jù)

void dlist_insert_back(dlist* pos, dlist_data_type x)

{

assert(pos);

dlist* newdlist = dlist_buy(x);

newdlist->prev = pos;

newdlist->next = pos->next;

pos->next->prev = newdlist;

pos->next = newdlist;

}

//刪除指定位置的節(jié)點(diǎn)

void dlist_erase(dlist* pos)

{

assert(pos);

dlist* del = pos;

pos->prev->next = pos->next;

pos->next->prev = pos->prev;

free(pos);

pos = NULL;

}

//銷毀

void dlist_destroy(dlist* phead)

{

assert(phead);

dlist* pcur = phead->next;

while (pcur != phead)

{

dlist* next = pcur->next;

free(pcur);

pcur = next;

}

free(pcur);

pcur = NULL;

}

test.c:

#define _CRT_SECURE_NO_WARNINGS

#include "dlist.h"

void test()

{

//dlist* plist = NULL;

//dlist_init(&plist);

dlist* plist = dlist_init();

//尾插

dlist_push_back(plist, 1);

dlist_push_back(plist, 2);

dlist_push_back(plist, 3);

dlist_print(plist);

//頭插

//dlist_push_front(plist, 1);

//dlist_push_front(plist, 2);

//dlist_push_front(plist, 3);

//dlist_print(plist);

//尾刪

//dlist_pop_back(plist);

//dlist_pop_back(plist);

//dlist_pop_back(plist);

//dlist_print(plist);

//頭刪

//dlist_pop_front(plist);

//dlist_print(plist);

//dlist_pop_front(plist);

//dlist_print(plist);

//dlist_pop_front(plist);

//dlist_print(plist);

//dlist* find = dlist_find(plist, 2);

//dlist_insert_back(find, 4);

//dlist_print(plist);

//dlist* find = dlist_find(plist, 2);

//dlist_erase(find);

//find = NULL;

//dlist_print(plist);

dlist_destroy(plist);

plist = NULL;//手動(dòng)置空

}

int main()

{

test();

return 0;

}

4、順序表和鏈表比較

順序表鏈表(雙向鏈表)存儲(chǔ)空間上邏輯、物理上都連續(xù)邏輯上連續(xù)、物理上不一定連續(xù)隨機(jī)訪問(wèn)復(fù)雜度O(1)復(fù)雜度O(N)任意位置插入或刪除數(shù)據(jù)需要挪動(dòng)數(shù)據(jù),復(fù)雜度O(N)只需要改變指針指向插入動(dòng)態(tài)順序表,空間不夠時(shí)擴(kuò)容,擴(kuò)容本身就有消耗,還容易空間浪費(fèi)沒(méi)有容量的概念應(yīng)用場(chǎng)景數(shù)據(jù)高效存儲(chǔ)+頻繁訪問(wèn)任意位置頻繁插入、刪除數(shù)據(jù)緩存利用率高低

順序表和鏈表優(yōu)勢(shì)互補(bǔ),在不同的應(yīng)用場(chǎng)景下能發(fā)揮各自的優(yōu)勢(shì)。

總結(jié)

如果應(yīng)用場(chǎng)景中需要頻繁進(jìn)行查找和刪除操作,并且能夠接受更多的內(nèi)存消耗,雙向鏈表可能更加合適。如果內(nèi)存比較有限或者對(duì)查找和刪除操作的效率要求不高,單鏈表可能更適合.

柚子快報(bào)邀請(qǐng)碼778899分享:【數(shù)據(jù)結(jié)構(gòu)】雙向鏈表

http://yzkb.51969.com/

文章來(lái)源

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19202170.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄