单链表插入元素 注释 c语言,数据结构之无头单链表的相关练习题——C语言实现(详细注释)...
本文中所用到的相關(guān)鏈表操作實(shí)現(xiàn)均在我上篇博客中:https://blog..net/haoziai905/article/details/87099287
1.刪除無(wú)頭單鏈表的非尾結(jié)點(diǎn)
這道題的重點(diǎn)就在于最后的非尾結(jié)點(diǎn)上,既然是非尾結(jié)點(diǎn),則說(shuō)明其下一個(gè)結(jié)點(diǎn)必定不為空。而我們通常所使用的刪除節(jié)點(diǎn)的方法都需要知道所要?jiǎng)h除節(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn),但是要找到鏈表中一個(gè)結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn)并容易,只能通過(guò)遍歷鏈表去尋找,但是遍歷鏈表的代價(jià)是非常大的。所以我們需要一個(gè)方法,讓我們不需要遍歷鏈表就能刪除這個(gè)結(jié)點(diǎn)。
首先,我們需要明白刪除一個(gè)結(jié)點(diǎn)的目的是什么。我們刪除一個(gè)結(jié)點(diǎn)的目的是為了刪除這個(gè)結(jié)點(diǎn)中所儲(chǔ)存的數(shù)據(jù),而不是一定要?jiǎng)h除這個(gè)結(jié)點(diǎn)才行。所以我們可以通過(guò)交換要?jiǎng)h除結(jié)點(diǎn)與下一個(gè)結(jié)點(diǎn)的數(shù)據(jù),再將下一個(gè)結(jié)點(diǎn)刪除就好了。而不需要去查找要?jiǎng)h除結(jié)點(diǎn)的上一個(gè)結(jié)點(diǎn)。
//刪除無(wú)頭單鏈表的非尾結(jié)點(diǎn)
void DelNodeNotTail(pNode pos)
{
assert(pos);
assert(pos->next);
//交換pos結(jié)點(diǎn)與pos下一結(jié)點(diǎn)的元素
pNode cur = pos->next;
pos->data = cur->data;
pos->next = cur->next;
//刪除pos結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)
free(cur);
cur = NULL;
}
2.在無(wú)頭單鏈表的一個(gè)位置前插入一個(gè)元素
這個(gè)題與上一個(gè)題類(lèi)似,插入元素也是需要知道要插入位置的前一個(gè)結(jié)點(diǎn)才行,但是遍歷鏈表的代價(jià)太大。所以我們也可以通過(guò)上一題交換結(jié)點(diǎn)中元素的方法來(lái)實(shí)現(xiàn),在該位置后插入一個(gè)新結(jié)點(diǎn),然后交換兩個(gè)結(jié)點(diǎn)中的元素即可。
//在無(wú)頭單鏈表的一個(gè)結(jié)點(diǎn)前插入一個(gè)結(jié)點(diǎn)
void InsertNode(pNode pos, DataType data)
{
assert(pos);
pNode cur = pos->next;//保存pos的下一結(jié)點(diǎn)位置
DataType tmp = pos->data;//保存pos結(jié)點(diǎn)的元素
//在pos位置后插入一個(gè)新結(jié)點(diǎn),并交換pos結(jié)點(diǎn)與新結(jié)點(diǎn)的元素
pos->next = BuyNode(data);
pos->data = data;
pos->next->data = tmp;
//將鏈表重新連接起來(lái)
pos->next->next = cur;
}
3.約瑟夫環(huán)
約瑟夫環(huán)是什么呢?約瑟夫環(huán)(約瑟夫問(wèn)題)是一個(gè)數(shù)學(xué)的應(yīng)用問(wèn)題:已知n個(gè)人(以編號(hào)1,2,3...n分別表示)圍坐在一張圓桌周?chē)木幪?hào)為k的人開(kāi)始報(bào)數(shù),數(shù)到m的那個(gè)人出列;他的下一個(gè)人又從1開(kāi)始報(bào)數(shù),數(shù)到m的那個(gè)人又出列;依此規(guī)律重復(fù)下去,直到圓桌周?chē)娜巳砍隽小N覀冃枰ㄟ^(guò)代碼來(lái)模擬約瑟夫環(huán)的過(guò)程,以此來(lái)知道誰(shuí)會(huì)留到最后。
//約瑟夫環(huán)
void JosephusCycle(pList* pplist, int k)
{
pNode cur = *pplist;
pNode del = NULL;
//當(dāng)cur==cur->next時(shí)說(shuō)明只剩下一個(gè)人了
while (cur != cur->next)
{
for (int i = 1; i < k; i++)
{
cur = cur->next;
}
printf("The %d is die!\n", cur->data);
del = cur->next->next;//保存cur的下下一個(gè)結(jié)點(diǎn)
cur->data = cur->next->data;//交換cur結(jié)點(diǎn)和下一結(jié)點(diǎn)的元素
free(cur->next);//刪除cur的下一結(jié)點(diǎn)
cur->next = del;//連接起鏈表
del = NULL;
}
*pplist = cur;
printf("The %d is live!\n", cur->data);
}
4.逆序單鏈表
要想將單鏈表逆序有兩種方法,第一個(gè)方法就是通過(guò)三個(gè)指針實(shí)現(xiàn),還有一種方法就是通過(guò)頭插來(lái)實(shí)現(xiàn)。當(dāng)我們將一個(gè)鏈表的結(jié)點(diǎn)從頭到尾一個(gè)一個(gè)的頭插到另一個(gè)新鏈表上時(shí),這時(shí)新產(chǎn)生的鏈表就是第一條鏈表逆序后的樣子。
//逆序鏈表:三指針?lè)?/p>
void ReverseList(pList* pplist)
{
assert(pplist);
//當(dāng)鏈表為空鏈表或者鏈表中只有一個(gè)元素時(shí),不需要逆序
if ((*pplist) == NULL || (*pplist)->next == NULL)
{
return;
}
pNode frist = *pplist;
pNode second = frist->next;
pNode third = second->next;
while (second != NULL)
{
second->next = frist;
frist = second;
second = third;
if (third != NULL)
{
third = third->next;
}
}
(*pplist)->next = NULL;
*pplist = frist;
}
//逆序鏈表:頭插法
void ReverseList(pList* pplist)
{
assert(pplist);
if ((*pplist) == NULL || ((*pplist)->next == NULL))
{
return;
}
pList pHead = NULL;
pNode cur = *pplist;
pNode tmp = cur->next;
while (cur)
{
//頭插
if (pHead == NULL)
{
pHead = cur;
}
else
{
cur->next = pHead;
pHead = cur;
cur = tmp;
if (tmp)
{
tmp = tmp->next;
}
}
}
(*pplist)->next = NULL;
*pplist = pHead;
}
5.冒泡排序
冒泡排序時(shí)最簡(jiǎn)單的一種排序方法,實(shí)現(xiàn)起來(lái)也并不復(fù)雜,但是我們通常所實(shí)現(xiàn)的冒泡排序都是通過(guò)數(shù)組或者是順序來(lái)實(shí)現(xiàn)的,那么在鏈表中我們應(yīng)該如何實(shí)現(xiàn)冒泡排序呢?
//冒泡排序
void BubbleSort(pList plist)
{
if (NULL == plist)
{
return;
}
pNode tail = NULL;
while (tail != plist)
{
pNode cur = plist;
pNode next = cur->next;
int flag = 0;//設(shè)置標(biāo)志位,提高排序效率
while (next != tail)
{
//升序排列
if (next->data < cur->data)
{
DataType tmp = next->data;
next->data = cur->data;
cur->data = tmp;
flag = 1;//如果單趟排序中發(fā)生了交換則將標(biāo)志位置1
}
else
{
cur = next;
next = next->next;
}
}
//標(biāo)志位為0則說(shuō)明為發(fā)生元素交換,則剩下的元素已經(jīng)有序,不需要排序,直接返回
if (flag == 0)
{
return;
}
tail = cur;
}
}
6.合并兩個(gè)有序鏈表,合并后依然有序
只需要一一對(duì)比兩個(gè)鏈表中元素的大小,然后按照我們所想要的順序?qū)⒋蟮脑鼗蛘咝〉脑匚膊迦胄骆湵碇屑纯伞?/p>
//合并兩個(gè)有序鏈表合并后仍然有序
pList Merge(pList plist1, pList plist2)
{
//1.兩個(gè)鏈表是一條鏈表
//2.兩條鏈表中有一條為空
//出現(xiàn)上面兩種情況都不需要合并鏈表
if (plist1 == plist2)
{
return plist1;
}
if (plist1 == NULL)
{
return plist2;
}
if (plist2 == NULL)
{
return plist1;
}
pList newlist = NULL;
pList cur = NULL;
while (plist1 != NULL && plist2 != NULL)
{
//比較兩條鏈表當(dāng)前第一個(gè)結(jié)點(diǎn)元素的大小
//升序排列則將元素較小的結(jié)點(diǎn)接在新鏈表后
if (plist1->data < plist2->data)
{
if (newlist == NULL)
{
newlist = plist1;
cur = newlist;
}
else
{
cur->next = plist1;
cur = cur->next;
}
plist1 = plist1->next;
}
else
{
if (newlist == NULL)
{
newlist = plist2;
cur = newlist;
}
else
{
cur->next = plist2;
cur = cur->next;
}
plist2 = plist2->next;
}
}
//當(dāng)其中一個(gè)鏈表已經(jīng)為空時(shí),直接將另一條鏈表的整條鏈表接在新鏈表后即可
if (plist1 == NULL && plist2 != NULL)
{
cur->next = plist2;
}
else if (plist1 != NULL && plist2 == NULL)
{
cur->next = plist1;
}
return newlist;
}
7.只遍歷鏈表一遍,找到中間結(jié)點(diǎn)
//只遍歷鏈表一遍,找到中間結(jié)點(diǎn)
pNode FindMidNode(pList plist)
{
//快慢指針?lè)?#xff0c;快指針?biāo)俣仁锹羔標(biāo)俣鹊膬杀?/p>
//當(dāng)快指針走到鏈表尾時(shí),則慢指針正好走到鏈表的中間位置
pNode fast = plist;
pNode slow = plist;
while (fast != NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
8.只遍歷一遍找到鏈表的倒數(shù)第K個(gè)結(jié)點(diǎn)
//只遍歷一遍找到鏈表的倒數(shù)第K個(gè)結(jié)點(diǎn)
pNode FindLastKNode(pList plist, int k)
{
if (plist == NULL)
{
return NULL;
}
int count = k;
pNode fast = plist;
pNode slow = plist;
//快指針先走K步
while (count--)
{
//如果快指針已經(jīng)為空則說(shuō)明鏈表中不足K個(gè)元素
if (fast == NULL)
{
return NULL;
}
fast = fast->next;
}
//快慢指針一起走,當(dāng)快指針為空時(shí),慢指針指的就是倒數(shù)第K個(gè)元素
while (fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
以上代碼均通過(guò)VS2017環(huán)境測(cè)試。
總結(jié)
以上是生活随笔為你收集整理的单链表插入元素 注释 c语言,数据结构之无头单链表的相关练习题——C语言实现(详细注释)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: for循环10000次花多长时间_我的三
- 下一篇: 长春理工大学c语言实验题库,长春理工大学