單鏈表 鄰接表

2022-07-30 18:30:17 字數 3393 閱讀 7046

近段時間在學習線段樹,二叉樹,字典樹,網路流,圖,都需要動態記憶體分配和建立鏈式結構,每次都是要看好長時間,乙個朋友告訴我,好好看看單鏈表,把最基礎的抓住,其他的就會迎刃而解。

動態記憶體分配對建立表、樹、圖和其他鏈式結構是特別有用的。

單鏈表       

結構體宣告型別:

struct node

int date;

node *next;

單鏈表的建立

struct node *p, *head;

head=null;

p=(struct node *)malloc(sizeof(struct node));//為節點分配記憶體空間

scanf("%d", &p->date);//把資料儲存到節點中或者直接賦值 p->date=a;

p->next=head; head=p;//把節點插入到鍊錶中,此方法為從頭插入,如果你輸入的是5 4 3 2 1,那麼裡面的順序會是 1 2 3 4 5

單鏈表的遍歷

struct node *p;//定義乙個指標在鍊錶之間移動;

p=head;//首先指向表中的第乙個元素

while(p)//如果沒有表尾就執行迴圈

printf("%d", p->date);//輸出p所指節點的元素值

p=p->next;//讓p指向下乙個節點

單鏈表的插入.

一般從中間插入.此時就應該找到要插入的是哪乙個結點後面,則稱此節點為要插入節點的前驅節點,用pre表示

struct node *p, *pre;

p=(struct node *)malloc(sizeof(struct node));//建立乙個新結點

p->next=pre->next;//將新節點的next指向前驅節點next指向的那個節點

pre->next=p;//將前驅節點的next指標指向新節點

單鏈表的刪除

刪除p點,此時我們就要找到p點的前驅節點

if(pre==null)

head=head->next;//如果要刪除的是第乙個節點,則改變頭指標的方向

else

pre->next=p->next;//否則改變前乙個節點,使它繞過要刪除的節點

free(p);//釋放要刪除的p這個節點的空間

鄰接表      

寫過之後我仍然無法明白,鄰接表的原理,再接再厲;

朋友不建議我直接用vector 類,他說我這樣用現成的會阻擋我的步伐,雖說現在進度是快了點,但如果最基礎的如何建立都不明白,又何談靈活的應用呢,根本轉化不成自己的東西,他說讓我先從最基礎的學起,盡量不用那些c++裡面的函式庫,他說讓我自己實現,這樣我的**和思維能力就會有很大的提高,加油!

說實話,我覺得鄰接表很神奇,如果是我我可能就不會如此建立,這是參考別人**,才知道這樣建立的

鄰接表,其實也要結構體型別宣告

struct node

int date;

node *next;

}g[n];

int head[n];

memset(head, -1, sizeof(head));

int cnt=0;

void addedge(int a, int b)

g[cnt].date=b;

g[cnt].next=head[a];

head[a]=cnt;

cnt++;

給你一組資料代表a與b相連

1 21 4

2 42 3

3 4cnt

0 1 23

4a 11

223g[cnt].date=b24

434next=head[a]-10

-12-1head[a]現在的值

也就是cnt++之後的值

head[1]=0

head[1]=1

head[2]=2

head[2]=3

head[3]=4

我們建立的鄰接表其實是這樣的(單向的)

1  與2 4相連

2  與4 3相連

3  與4   相連

head[0]=-1;

head[1]=1;

head[2]=3;

head[3]=4;

head[4]=-1;

你們又沒有發現什麼,類似與棧,也就是說cnt 0->1  如果遍歷的話,就for(j=head[a]; j!=-1; j=g[j].next) 一般a從start開始一般是1,到end;這時候觀察一下,head[1]=1;此時g[j] 剛好就是g[1]也就是與1相連的4,之後j=0;剛好是與1相連的2;類似與棧,我們將1壓入棧底,之後壓入4;所以我們尋找的時候首先搜尋到的head[a]最後進棧的,之後再向前推,由此,你明白為什麼g[cnt].next=head[a];

觀察紫色與紫色數字之間的關係,紅色與 紅色數字之間的關係,再 看他們這兩行 的『a』值,竟然是相同的

而且head[a]=cnt;就本列來說; 所以你就會明白 其實next=head[a]的含義就是建立關係,即使是在g陣列中

我建立的是單向的,如果是雙向路這樣做也可以,只用新增反邊就行了;

通俗的說 與節點 a相連的第一條邊是g[cnt].date,那麼『a』相連的下一條邊是g[cnt].next;而g[cnt].next又等於下一條邊的陣列的下標

g[cnt1].next=head[a]; head[a]=cnt2; 你們看看領悟領悟  這裡cnt1 與cnt2 就是與 『a』相連的邊的陣列的下標;

這裡推薦乙個部落格,寫的簡潔明瞭,我搜的時候搜到的;

大家可以觀察一下,next這一行, 與cnt這一行的關係。其實就可以發現next其實代表與  『1』  相連的第乙個數是 『2』  第二個數也就是(next)下乙個數是 『4』;這就是為什麼a不存入其中的原因;

同理 與『2』 相連的是『4』 之後的是『3』;依次進入表中,看過這個大家也就明白為什麼next=head[a]了吧,每次head[a]都會更新為cnt現在的值也就是記錄,與『a'相連的這個數『b』所存在的位置;

當我們遍歷的時候,就可通過尋找g[i].next來尋找與『a』相連的其他數;因此每次addage這個函式裡面 可以總結兩條 更新過後的head[a]=cnt;

之前用的是#include這個標頭檔案,但是其實這樣不好,本末倒置了,如果我先理解上面那一種,我理解vector類就會更清晰,但是先理解vector類在理解基礎的建立過程就會很艱難;

(1)vectora;//相當於申請乙個一維陣列

a.push_back(i);//壓入

a.size();//得到長度

a.clear();//清空

(2)vectorg[n];相當於vector>g//相當於申請乙個二維陣列

g.resize(n+1);//申請記憶體

g[i].push_back(j);

g[i].size();

g[i].clear();

一維陣列模擬單鏈表 鄰接表和雙鏈表 模板

單鏈表 模板題 acwing 826.單鏈表 實現乙個單鏈表,鍊錶初始為空,支援三種操作 1 向煉表頭插入乙個數 2 刪除第k個插入的數後面的數 3 在第k個插入的數後插入乙個數 現在要對該鍊錶進行m次操作,進行完所有操作後,從頭到尾輸出整個鍊錶。注意 題目中第k個插入的數並不是指當前鍊錶的第k個數...

單鏈表 鍊錶倒置

鍊錶屬於動態資料結構,可以模擬成一 環 接一 環 的鏈條,這裡每一 環 視作乙個結點,結點串在一起形成鍊錶。這種資料結構非常靈活,結點數目無須事先指定,可以臨時生成。每個結點有自己的儲存空間,結點間的儲存空間也無需連線,結點之間的串連由指標來完成,指標的操作又極為靈活方便,無須移動大批資料,只需修改...

鍊錶之單鏈表

上週給前端的小夥伴們進行了講課,想著總結一下,但是直到推到現在,我才開始。上週講課的內容是es6和鍊錶。我大致把鍊錶的內容總結一下,也算是個回顧。一 初始鍊錶 鍊錶定義 使用一組任意的儲存單元儲存線性表的資料元素 可連續,也可是不連續 它是一種順序儲存。也就是說,鍊錶是線性結構,各個元素的儲存位置都...