日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何在O(1)的时间里删除单链表的结点

發布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何在O(1)的时间里删除单链表的结点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目是這樣的:給你一個單鏈表的表頭,再給你其中某個結點的指針,要你刪除這個結點,條件是你的程序必須在O(1)的時間內完成刪除。

由于有的同學對鏈表還不是很熟悉,本文盡量描述的通俗易懂,老鳥請直接跳過前面一大段。

鏈表結構如下:

struct node {int val;node* next; };
題目不是很難,很快就能想到好辦法:)

首先回顧一下普通的刪除方法,首先通過表頭,找到待刪除結點(設為B)的前一個結點(設為A),將A的指向改一下就行,然后刪除掉B結點就行了。要刪除的結點一定要delete掉,這不僅是個好習慣,而且能避免將來項目中可能造成的內存泄露的嚴重問題。

void DeleteNode_On(node *LinkList, node *p) {printf("delete:%d\n", p->val);node *s = LinkList;while(s->next != p)s = s->next;s->next = s->next->next;delete(p); }

這個算法主要耗時在于查找前一個結點,所以是O(n)的算法。

那么既然要求是O(1),顯然不能再去for一遍了,聯想到數組的刪除,這個問題就比較好解決了。

首先我們很容易就能得到待刪除結點,即B結點的后一個結點C,然后將C的值賦值給B結點的值,相當于數組刪除時候的覆蓋,現在B結點和C結點一模一樣了,接下來就相當簡單了吧,我們不刪B,直接利用B刪掉C就行了,方法簡單,時間O(1)。


但是仔細想想這個算法有個很明顯的缺陷,如果待刪除結點是最后一個結點呢?這個時候似乎沒有什么好的解決辦法,只能老老實實的O(n)了。現在我們來看看平均時間復雜度:

符合題目要求。

void DeleteNode_O1(node *LinkList, node *p) {printf("delete:%d\n", p->val);if(p->next != NULL) //如果p不是末尾結點, 則讓后一個結點覆蓋掉p, 然后刪除后一個結點{p->val = p->next->val;node *tmp = p->next;p->next = p->next->next;delete(tmp);}else // 如果p是末尾結點, 則找到p的前一個結點然后正常刪除{node *s = LinkList;while(s->next != p)s = s->next;s->next = s->next->next;delete(p);} }
最后附上完整測試代碼:

#include<iostream>using namespace std;struct node {int val;node* next; };void CreateLinkList(node *LinkList) {node *s = LinkList;for(int i = 0; i < 10; i++){node *t = new node;t->val = i;t->next = NULL;s = s->next = t;} }void ShowLinkList(node * LinkList) {node *s = LinkList->next;while(s = s->next)printf("%d ", s->val);putchar(10); }void DeleteNode_On(node *LinkList, node *p) {printf("delete:%d\n", p->val);node *s = LinkList;while(s->next != p)s = s->next;s->next = s->next->next;delete(p); }void DeleteNode_O1(node *LinkList, node *p) {printf("delete:%d\n", p->val);if(p->next != NULL) //如果p不是末尾結點, 則讓后一個結點覆蓋掉p, 然后刪除后一個結點{p->val = p->next->val;node *tmp = p->next;p->next = p->next->next;delete(tmp);}else // 如果p是末尾結點, 則找到p的前一個結點然后正常刪除{node *s = LinkList;while(s->next != p)s = s->next;s->next = s->next->next;delete(p);} }int main() {node *LinkList = new node;CreateLinkList(LinkList);ShowLinkList(LinkList);node *p = LinkList->next;for(int i = 0; i < 3; i++)p = p->next;DeleteNode_On(LinkList, p);ShowLinkList(LinkList);p = LinkList->next;for(int i = 0; i < 8; i++)p = p->next;DeleteNode_O1(LinkList, p);ShowLinkList(LinkList);p = LinkList->next;for(int i = 0; i < 4; i++)p = p->next;DeleteNode_O1(LinkList, p);ShowLinkList(LinkList);getchar();return 0; } void DeleteNode(ListNode** pHead, ListNode* pToBeDeleted){//刪除鏈接節點算法 時間復雜度為O(1);if (!pHead || !pToBeDeleted){return;}if (pToBeDeleted->m_pNext != NULL){ListNode* pNext = pToBeDeleted->m_pNext;pToBeDeleted->m_nValue = pNext->m_nValue;pToBeDeleted->m_pNext = pNext->m_pNext;delete pNext;pNext = NULL;}else if (*pHead ==pToBeDeleted){delete pToBeDeleted;pToBeDeleted = NULL;*pHead = NULL;}else{ListNode* pNode = *pHead;while (pNode->m_pNext != pToBeDeleted){ pNode = pNode->m_pNext;}pNode->m_pNext = NULL;delete pToBeDeleted;pToBeDeleted = NULL;} } void Test(ListNode* pListHead, ListNode* pNode){printf("the original list is:\n");PrintList(pListHead);printf("The node to be deleted is:\n");PrintList(pNode);DeleteNode(&pListHead, pNode);printf("the result list is:\n");PrintList(pListHead); }void Test1(){ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);CoonnectListNode(pNode1, pNode2);CoonnectListNode(pNode2, pNode3);CoonnectListNode(pNode3, pNode4);CoonnectListNode(pNode4, pNode5);Test(pNode1, pNode5);DestroyList(pNode1);}

總結

以上是生活随笔為你收集整理的如何在O(1)的时间里删除单链表的结点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。