關(guān)于鏈表
創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括菏澤網(wǎng)站建設(shè)、菏澤網(wǎng)站制作、菏澤網(wǎng)頁制作以及菏澤網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,菏澤網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到菏澤省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!鏈表是一種動(dòng)態(tài)的數(shù)據(jù)結(jié)構(gòu),因?yàn)樵趧?chuàng)建鏈表時(shí)無需知道鏈表的長度,當(dāng)插入一個(gè)節(jié)點(diǎn)時(shí),只需要為新的節(jié)點(diǎn)分配內(nèi)存,其空間效率和數(shù)組相比要高,但是每次都要?jiǎng)?chuàng)建空間所以時(shí)間不是很高
單向鏈表定義節(jié)點(diǎn)
struct ListNode { int m_value; ListNode* m_pNext; };
在鏈表后面添加節(jié)點(diǎn)
void AddToTail(ListNode** pHead,int value)//時(shí)間效率O(N) { ListNode* pnewNode=new ListNode();//創(chuàng)建新結(jié)點(diǎn) pnewNode->m_value=value; pnewNode->m_pNext=NULL; if(pHead==NULL)//當(dāng)頭結(jié)點(diǎn)為空 { pHead=pnewNode; } else//不為空 { ListNode*pNode=*pHead; while(pNode->m_next!=NULL)//遍歷找到最后一個(gè)節(jié)點(diǎn) { pNode=pNode->m_next; } pNode->m_next=pnewNode; } }
刪除其中某節(jié)點(diǎn)
void RemoveNode(ListNode**pHead, int value) { if (pHead == NULL||*pHead==NULL)//頭結(jié)點(diǎn)為空 return; ListNode*pDelete = NULL; if ((*pHead)->m_value == value) { pDelete = *pHead; *pHead = (*pHead)->m_pNext; } else { ListNode*pNode = *pHead; //遍歷查找要?jiǎng)h除結(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn) while (pNode->m_pNext!=NULL &&pNode->m_pNext-> m_value != value) { pNode = pNode->m_pNext; } pDelete = pNode->m_pNext; pNode->m_pNext = pDelete->m_pNext; if (pDelete != NULL) { delete pDelete; pDelete = NULL; } }
題目1:
輸入一個(gè)鏈表頭結(jié)點(diǎn),從頭到尾反過來打印這個(gè)結(jié)點(diǎn)值(不改變結(jié)點(diǎn)結(jié)構(gòu))
程序1.0
若鏈表為空直接返回鏈表,若只有一個(gè)節(jié)點(diǎn),打印此結(jié)點(diǎn);若有多個(gè)結(jié)點(diǎn),設(shè)置一個(gè)計(jì)數(shù)器,先、遍歷結(jié)點(diǎn)統(tǒng)計(jì)結(jié)點(diǎn)個(gè)數(shù),再循環(huán)結(jié)點(diǎn)數(shù)次,在這個(gè)循環(huán)里再依次找到倒數(shù)第一個(gè)、倒數(shù)第二個(gè)、倒數(shù)第N個(gè)節(jié)點(diǎn)
void PrintListReverse(ListNode*pHead)//時(shí)間復(fù)雜度O(N^2) { while (pHead == NULL)//沒有結(jié)點(diǎn) return; if (pHead->m_pNext == NULL)//一個(gè)節(jié)點(diǎn) { cout << pHead->m_value; return; } ListNode*pNode = pHead; int count =1; while (pNode->m_pNext != NULL) { count++; pNode = pNode->m_pNext; } while (count != 0) { for (int i = 1; i < count; i++) { pNode = pNode->m_pNext;//找到倒數(shù)第N個(gè)節(jié)點(diǎn)的前一個(gè)結(jié)點(diǎn) } cout << pNode->m_value << "->"; count--; } }
程序2.0
上面用循環(huán)實(shí)現(xiàn),過于復(fù)雜且效率不高,所以第二次使用棧來完成,棧有“先入后出”的特性,所以用棧來實(shí)現(xiàn)更為方便,沒遇到一個(gè)不為空的結(jié)點(diǎn)就把它放到棧中
void PrintListReverse(ListNode*pHead)//時(shí)間復(fù)雜度O(N) { stacks1; ListNode*pNode = pHead; while (pNode->m_pNext != NULL) { s1.push(pNode); pNode = pNode->m_pNext; } while (!s1.empty()) { cout << s1.top()->m_value << "->"; s1.pop(); } }
程序3.0
我們知道遞歸的本質(zhì)就是棧,所以我們也可以用棧來實(shí)現(xiàn)它,先遞歸后面的結(jié)點(diǎn),一直遞歸到?jīng)]有結(jié)點(diǎn),再輸出該結(jié)點(diǎn)
void PrintListReverse(ListNode*pHead) { if (pHead != NULL) { if (pHead->m_pNext != NULL)//遞歸停止條件 { PrintListReverse(pHead->m_pNext); } cout << pHead->m_value << "->"; } }
遞歸寫法雖然看起來要簡潔的多,但是若結(jié)點(diǎn)超級(jí)長則會(huì)導(dǎo)致函數(shù)調(diào)用棧溢出,所以在實(shí)現(xiàn)是最好使用顯示調(diào)用棧的方式來實(shí)現(xiàn)
題目2:
題目:在O(1)的時(shí)間刪除鏈表結(jié)點(diǎn)
分析:要?jiǎng)h除一個(gè)節(jié)點(diǎn),O(n)的方法是從頭到尾遍歷找到要?jiǎng)h除的結(jié)點(diǎn)(即順序查找),并在鏈表中刪除它。
程序1.0 刪除一個(gè)節(jié)點(diǎn)復(fù)雜度O(n)
void DeleteNode(ListNode**pListHead, ListNode* pToBeDeleted) { if (pListHead || pToBeDeleted) return; ListNode*cur = *pListHead; while (cur->m_pNext != pToBeDeleted) { cur = cur->m_pNext; } cur->m_pNext = pToBeDeleted->m_pNext; delete pToBeDeleted; }
程序2.0
刪除一個(gè)結(jié)點(diǎn)復(fù)雜度O(1),找到要?jiǎng)h除的結(jié)點(diǎn)pToBeDelete的后面的結(jié)點(diǎn)del,把這個(gè)結(jié)點(diǎn)的值覆蓋要?jiǎng)h除的結(jié)點(diǎn),刪除這個(gè)后面的結(jié)點(diǎn)
void DeleteNode(ListNode**pListHead, ListNode* pToBeDeleted) { if (pListHead || pToBeDeleted)//若為空 return; if ((*pListHead == pToBeDeleted) && (pToBeDeleted->m_pNext == NULL))//只有一個(gè)節(jié)點(diǎn)且刪除這個(gè)結(jié)點(diǎn) { delete pToBeDeleted; pToBeDeleted = NULL; *pListHead = NULL; return; } if (pToBeDeleted->m_pNext == NULL)//有多個(gè)結(jié)點(diǎn)pToBeDeleted為尾節(jié)點(diǎn)O(N) { ListNode*cur = *pListHead; while (cur->m_pNext != pToBeDeleted) { cur = cur->m_pNext; } cur->m_pNext = NULL; delete pToBeDeleted; pToBeDeleted = NULL; } else if (pToBeDeleted->m_pNext)//有多個(gè)結(jié)點(diǎn)且pToDeleted不為尾 { ListNode*del = pToBeDeleted->m_pNext; pToBeDeleted->m_value = del->m_value; pToBeDeleted->m_pNext = del->m_pNext; delete del; del = NULL; } }
題目3:
輸入一個(gè)鏈表,輸出鏈表中倒數(shù)第K個(gè)節(jié)點(diǎn)
分析:定義兩個(gè)指針均指向頭,一個(gè)指針先走K步,另一個(gè)等第一個(gè)指針走k步后再和其一起走,知道第一個(gè)走到空時(shí)第二個(gè)指針即走到倒數(shù)第k個(gè)節(jié)點(diǎn)
考慮:1.輸入的頭結(jié)點(diǎn)是否為空,訪問空指針指向的內(nèi)存導(dǎo)致程序奔潰 2.鏈表的結(jié)點(diǎn)是否大于k 3.k若為0怎么辦
ListNode* FindKthToTail(ListNode*pHead, int k) { if (pHead == NULL || k == 0) return NULL; ListNode *fast = pHead; ListNode*slow = pHead; while (--k) { if (fast->m_pNext != NULL) fast = fast->m_pNext; else return NULL; } while (fast->m_pNext) { slow = slow->m_pNext; fast = fast->m_pNext; } return slow; }
相似快慢指針問題
1.題目:求鏈表中間結(jié)點(diǎn)
設(shè)置指向頭的快、慢指針,快指針每次走兩步,慢的每次走一步,當(dāng)快指針走到末尾時(shí),慢指針剛好在中間
ListNode*FindMidNode(ListNode*pHead) { if (pHead == NULL) return NULL; ListNode*fast = pHead; ListNode*slow = pHead; while (fast->m_pNext&&fast) { fast = fast->m_pNext->m_pNext; slow = slow->m_pNext; } return slow; }
2.判斷一個(gè)指針是否構(gòu)成環(huán)形
同上方法,如果帶環(huán),則快指針一定會(huì)追上慢指針,若快指針走到了鏈尾(NULL),則不是環(huán)形鏈表
ListNode*IsCircleList(ListNode*pHead) { if (pHead == NULL) return NULL; ListNode*fast = pHead; ListNode*slow = pHead; while (fast&&fast->m_pNext) { fast = fast->m_pNext->m_pNext; slow = slow->m_pNext; if (slow == fast) return slow; } return NULL; }
題目4:
反轉(zhuǎn)鏈表
void ReverseList(ListNode*pHead) { if (pHead == NULL||pHead->m_pNext==NULL) return; ListNode*newHead = NULL; ListNode*cur = pHead; ListNode*prev = pHead; while (cur) { prev = cur; cur = cur->m_pNext; prev->m_pNext = newHead; newHead = prev; } pHead = newHead; }
題目5:
合并兩個(gè)排序的鏈表
ListNode*Merge(ListNode*pHead1, ListNode*phead2) { if (pHead1 == NULL) return phead2; if (phead2 == NULL) return pHead1; ListNode*newHead = NULL; while (pHead1&&phead2) { if (pHead1->m_value < phead2->m_value) { newHead = pHead1; newHead->m_pNext = Merge(pHead1->m_pNext, phead2); } else { newHead = phead2; newHead->m_pNext = Merge(pHead1, phead2->m_pNext); } } return newHead; }
創(chuàng)新互聯(lián)www.cdcxhl.cn,專業(yè)提供香港、美國云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開啟,新人活動(dòng)云服務(wù)器買多久送多久。