三 鍊錶(實踐)

2021-08-29 01:17:59 字數 4573 閱讀 4280

如何輕鬆寫鍊錶的**?

警惕指標丟失和記憶體洩漏

利用哨兵(頭結點)簡化實現難度

重點留意邊界條件處理

舉例畫圖,輔助思考

// 定義結點 node

typedef

struct node node;

// 定義指向結點 node 型別物件的指標 linklist

typedef

struct node *linklist;

struct dnode
由於單鏈表的結構中沒有定義表長,所以不能事先知道要迴圈多少次,因此不方便用for迴圈來控制迴圈。==》while迴圈

# define ok 1

# define error 0

# define true 1

# define false 0

typdef int status;

//status是函式的型別,其值為函式結果狀態碼,eg:ok等

/*初始條件:順序線性表l已存在,1≤i≤listlength(l)*/

/*操作結果: 用e返回l中第i個資料元素的值*/

/*初始條件:順序線性表l已存在,1≤i≤listlength(l)*/

/*操作結果:在l中第i個位置之前插入新的資料元素e,l的長度加1*/

status listinsert

(linklist *l,

int i, elemtype e)if(

!p || j>i )

// 第i個結點不存在

return error;

s =(linklist)

malloc

(sizeof

(node));

//生成新的結點

s->data = e;

s->next = p->next;

//將p的後繼結點賦值給s的後繼

p->next = s;

//將s賦值給p的後繼

return ok;

}

p->next = p->next->next

用q取代p->next的話,上面等價於:

}

單鏈表的整表建立過程就是乙個動態生成鍊錶的過程。由「空表」的初始狀態,依次建立各元素結點,並逐個插入鍊錶。

頭插法

/* 隨機產生n個元素的值,建立帶頭結點的單鏈表l */

void

createlisthead

(linklist *l,

int n)

}

尾插法

/* 隨機產生n個元素的值,建立帶頭結點的單鏈表l */

void

createlisthead

(linklist *l,

int n)

r->next=

null

;}

/*初始條件:順序線性表l已存在,操作結果:將l充值為空表*/

status clearlist

(linklist *l)

(*l)

->next =

null

;return ok;

}

法一:反向遍歷鍊錶就類似於事先遍歷的節點後輸出,即「先進後出」,那麼可以將鍊錶遍歷存放於棧中,其後遍歷棧依次彈出棧節點,達到反向遍歷效果。

void

printlinkedlistreversinglybystack

(node *head)

while

(!nodesstack.

empty()

)}//2.遞迴

void

printlinkedlistreversinglyrecursively

(node *head)

printf

("%d\t"

, head-

>value);}

}

判斷鍊錶是否有環路,獲取連線點,計算環的長度

此題很有意思,具體詳細請參考:

判斷是否含有環:slow和fast,slow指標每次走一步,fast指標每次走兩步,若是鍊錶有環,fast必能追上slow(相撞),若fast走到null,則不含有環。

//判斷是否含有環

bool

containloop

(node* head)

node* slow = head;

node* fast = head;

while

(slow!=fast&&fast-

>next!=

null)if

(fast==

null

)return

true

;}

判斷環的長度:在相撞點處,slow和fast繼續走,當再次相撞時,slow走了length步,fast走了2*length步,length即為環得長度。

//獲得環的長度

intgetlooplength

(node* head)

node* slow = head;

node* fast = head;

while

(slow!=fast&&fast-

>next!=

null)if

(fast==

null

)//slow和fast首次相遇後,slow和fast繼續走

//再次相遇時,即slow走了一圈,fast走了兩圈

int length =0;

while

(slow!=fast)

return length;

}

//獲得環的連線點

node*

getjoinpoit

(node* head)

node* slow = head;

node* fast = head;

while

(slow!=fast&&fast-

>next!=

null)if

(fast==

null

) node* fromhead = head;

node* fromcrashpoint = slow;

while

(fromcrashpoint!=fromhead)

return fromhead;

}

用slow和fast指標標記,slow每次走一步,fast每次走兩步,當fast到尾節點時,slow就相當於總長度的一半,即在中間節點。

//找出中間節點

node*

findmidnode

(node* head)

return slow;

}

用slow和fast指標標記,fast指標事先走k步,然後slow和fast同時走,當fast到達末節點時,slow在fast的前k個節點,即為倒數第k個節點。

//找出倒數第k個節點

node*

findknode

(node* head,

int k)

temp2 =temp2-

>next;

}while

(temp2-

>next !=

null

&&temp2-

>next-

>next!=

null

)return temp1;

}

LeetCode 鍊錶(三)

本組囊括鍊錶相關題目,難度不等。題目描述 中等 官方題解 使用成環的思想,原鍊錶連成環,再斷開環和生成新鏈頭和鏈尾即可 首先將原鍊錶的鏈頭和鏈尾連線起來形成環,然後再n k的節點後斷開環,下乙個節點n k 1即是新的鍊錶的鏈頭,n k是新鍊錶的鏈尾。上述考慮的是k n的情況,如果k n呢 考慮k k...

鍊錶 三 雙向鍊錶

前兩篇部落格中介紹的鏈式儲存結構中只有乙個指示直接後繼的指標域。因此,從單鏈表中的某個結點出發,之能向後遍歷每個結點,所尋找這個結點的直接前驅只能向用頭結點出。而若在每個結點的指標域中再加入乙個指向當前結點直接前驅的指標,就可以克服以上問題。雙向鍊錶,帶頭節點,頭的前驅為null,尾的後繼為null...

鍊錶 三 雙向鍊錶

1.概念 雙向鍊錶 double linked list 的節點有兩個指標,乙個指向直接前驅,乙個指向直接後繼。2.優點 查詢直接前驅執行時間為o 1 單鏈表為o n 3.儲存結構 雙向鍊錶 typedef struct dulnodedulnode,dulinklist 4.簡單例項 includ...