近段時間在學習線段樹,二叉樹,字典樹,網路流,圖,都需要動態記憶體分配和建立鏈式結構,每次都是要看好長時間,乙個朋友告訴我,好好看看單鏈表,把最基礎的抓住,其他的就會迎刃而解。
動態記憶體分配對建立表、樹、圖和其他鏈式結構是特別有用的。
單鏈表
結構體宣告型別:
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和鍊錶。我大致把鍊錶的內容總結一下,也算是個回顧。一 初始鍊錶 鍊錶定義 使用一組任意的儲存單元儲存線性表的資料元素 可連續,也可是不連續 它是一種順序儲存。也就是說,鍊錶是線性結構,各個元素的儲存位置都...