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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

链表反转问题收集

發布時間:2024/4/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 链表反转问题收集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目:輸入一個鏈表的頭結點,反轉該鏈表,并返回反轉后鏈表的頭結點。鏈表結點定義如下:
struct
ListNode
{
??????int??????? m_nKey;
?????? ListNode* m_pNext;
};
分析:這是一道廣為流傳的微軟面試題。由于這道題能夠很好的反應出程序員思維是否嚴密,在微軟之后已經有很多公司在面試時采用了這道題。
為了正確地反轉一個鏈表,需要調整指針的指向。與指針操作相關代碼總是容易出錯的,因此最好在動手寫程序之前作全面的分析。在面試的時候不急于動手而是一開始做仔細的分析和設計,將會給面試官留下很好的印象,因為在實際的軟件開發中,設計的時間總是比寫代碼的時間長。與其很快地寫出一段漏洞百出的代碼,遠不如用較多的時間寫出一段健壯的代碼。
為了將調整指針這個復雜的過程分析清楚,我們可以借助圖形來直觀地分析。假設下圖中l、m和n是三個相鄰的結點:
a?b??l??mànà
假設經過若干操作,我們已經把結點l之前的指針調整完畢,這些結點的m_pNext指針都指向前面一個結點。現在我們遍歷到結點m。當然,我們需要把調整結點的m_pNext指針讓它指向結點l。但注意一旦調整了指針的指向,鏈表就斷開了,如下圖所示:
a?b?l?m??nà
因為已經沒有指針指向結點n,我們沒有辦法再遍歷到結點n了。因此為了避免鏈表斷開,我們需要在調整m的m_pNext之前要把n保存下來。
接下來我們試著找到反轉后鏈表的頭結點。不難分析出反轉后鏈表的頭結點是原始鏈表的尾位結點。什么結點是尾結點?就是m_pNext為空指針的結點。
基于上述分析,我們不難寫出如下代碼:
///
// Reverse a list iteratively
// Input: pHead - the head of the original list
// Output: the head of the reversed head
///
ListNode* ReverseIteratively(ListNode* pHead)
{
?????? ListNode* pReversedHead = NULL;
?????? ListNode* pNode = pHead;
?????? ListNode* pPrev = NULL;
??????while(pNode != NULL)
?????? {
????????????// get the next node, and save it at pNext
???????????? ListNode* pNext = pNode->m_pNext;
????????????// if the next node is null, the currect is the end of original
????????????// list, and it's the head of the reversed list
????????????if(pNext == NULL)
?????????????????? pReversedHead = pNode;

????????????// reverse the linkage between nodes
???????????? pNode->m_pNext = pPrev;

????????????// move forward on the the list
???????????? pPrev = pNode;
???????????? pNode = pNext;
?????? }

??????return pReversedHead;
}
擴展:本題也可以遞歸實現。感興趣的讀者請自己編寫遞歸代碼。

單向鏈表的反轉是一個經常被問到的一個面試題,也是一個非常基礎的問題。比如一個鏈表是這樣的: 1->2->3->4->5 通過反轉后成為5->4->3->2->1。最容易想到的方法遍歷一遍鏈表,利用一個輔助指針,存儲遍歷過程中當前指針指向的下一個元素,然后將當前節點元素的指針反轉后,利用已經存儲的指針往后面繼續遍歷。源代碼如下:

struct linka {int data;linka* next; };void reverse(linka*& head) {if(head ==NULL)return;linka*pre, *cur, *ne;pre=head;cur=head->next;while(cur){ne = cur->next;cur->next = pre;pre = cur;cur = ne;}head->next = NULL;head = pre; }

還有一種利用遞歸的方法。這種方法的基本思想是在反轉當前節點之前先調用遞歸函數反轉后續節點。源代碼如下。不過這個方法有一個缺點,就是在反轉后的最后一個結點會形成一個環,所以必須將函數的返回的節點的next域置為NULL。因為要改變head指針,所以我用了引用。算法的源代碼如下:

linka* reverse(linka* p,linka*& head) {if(p == NULL || p->next == NULL){head=p;return p;}else{linka* tmp = reverse(p->next,head);tmp->next = p;return p;} }

總結

以上是生活随笔為你收集整理的链表反转问题收集的全部內容,希望文章能夠幫你解決所遇到的問題。

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