【Garry逆襲數據結構】之 鏈表 知識點學習--Android地基系列(一)

轉載請註明:http://blog.csdn.net/lrs123123/article/details/43971015  (第一次被盜帖也是醉了)


曾經有多少人,因爲年少不懂事,不知道數據結構是多麼一個“白富美”(“高富帥”),而到了發現的時候就總是感嘆,哎,年輕時怎麼沒發現他/她是這麼一個潛力股(美人胚),大腿直捏卻又無法補救,怎麼辦?不用怕,Garry帶你慢慢逆襲數據結構,不管他/她多麼高冷,在我們的進攻下,她終會~~~(博主大半夜一直在構思博文還沒完全寫好還請各位看官輕拍~~)


首先,這是在看別人整理過之後,自己進一步整理出來供大家參考的“逆襲寶典”,都是各種筆試面試常見的必考題目(博主痛在心~),嘻嘻嘻,鏈表的基礎知識我就不寫了,太多人寫了。


看前注意!!!!!!!涉及C知識較多,C知識我以後再考慮是否寫一篇附加文可以輔助以後的Android必備地基系列博文


struct ListNode
{
    int data;
    ListNode * Next;

}; 


逆襲1:鏈表節點有幾個

思路:若鏈表爲空,返回0;循環判斷鏈表下一個指針是否爲空,no,長度++(初始化用unsigned int  length = 0),直到下一個爲null,返回長度

// 求單鏈表中結點的個數  
unsigned int GetListLength(ListNode * pHead)  
{  
 if(pHead == NULL)  
  return 0;  
  
 unsigned int mLength = 0;  
 ListNode * pCurrent = pHead;  
 while(pCurrent != NULL)  
 {  
  mLength ++;  
  pCurrent = pCurrent->m_pNext;  
 }  
 return mLength ;  
}  

逆襲2:反轉單鏈表

思路:從頭到尾遍歷原鏈表,每遍歷一個結點,將其摘下放在新鏈表的最前端。

注意鏈表爲空和只有一個結點的情況。時間複雜度爲O(n); (這是方法2)

如何把一個單鏈表進行反轉?
方法1:將單鏈表儲存爲數組,然後按照數組的索引逆序進行反轉。
方法2:使用3個指針遍歷單鏈表,逐個鏈接點進行反轉。

方法3:從第2個節點到第N個節點,依次逐節點插入到第1個節點(head節點)之後,最後將第一個節點挪到新表的表尾。

方法4:   遞歸(相信我們都熟悉的一點是,對於樹的大部分問題,基本可以考慮用遞歸來解決。但是我們不太熟悉的一點是,對於單鏈表的一些問題,也可以使用遞歸。可以認爲單鏈表是一顆永遠只有左(右)子樹的樹,因此可以考慮用遞歸來解決。或者說,因爲單鏈表本身的結構也有自相似的特點,所以可以考慮用遞歸來解決)

參考自:

http://blog.csdn.net/feliciafay/article/details/6841115

貼上代碼,

ListNode* ReverseList(ListNode* head)  
{  
  
 if(NULL==head|| NULL==head->next)   
      return head;    //少於兩個節點沒有反轉的必要。  
 ListNode* p = head;  
 ListNode* q = head->next;  
 ListNode* r;  
    head->next = NULL;        //舊的頭指針是新的尾指針,next需要指向

NULL  
    while(q){  
        r = q->next; //先保留下一個step要處理的指針  
        q->next = p; //然後p q交替工作進行反向  
        p = q;   
        q = r;   
    }  
 head=p; // 最後q必然指向NULL,所以返回了p作爲新的頭指針  
    return head;      
}  


逆襲3:查單鏈表倒數第K個結點

思路:最普遍的方法是,先統計單鏈表中結點的個數,然後再找到第(n-k)個結點。注意鏈表爲空,k爲0,k爲1,k大於鏈表中節點個數時的情況。時間複雜度爲O(n)
這裏主要講一下另一種,這種思路在其他題目中也會有應用。主要思路就是使用兩個指針,先讓前面的指針走到正向第k個結點,這樣前後兩個指針的距離差是k-1,之後前後兩個指針一起向前走,前面的指針走到最後一個結點時,後面指針所指結點就是倒數第k個結點。(推薦逆襲使用此法~)

實際可逆襲場景
已知一個帶有表頭結點的單鏈表,結點結構爲
假設該鏈表只給出了頭指針list。在不改變鏈表的前提下,請設計一個儘可能高效的算法,查找鏈表中倒數第k個位置上的結點(k爲正整數)。若查找成功,算法輸出該結點的 data域的值,並返回1;否則,只返回0。要求:
1)描述算法的基本設計思想。
2)描述算法的詳細實現步驟。

3)根據設計思想和實現步驟,釆用程序設計語言描述算法(使用C、C++或Java語言實現),關鍵之處請給出簡要註釋。


逆襲支招:
1)算法的基本設計思想如下:(思想其實就是上上邊的另一個思路)
問題的關鍵是設計一個儘可能高效的算法,通過鏈表的一趟遍歷,找到倒數第k個結點的位置。算法的基本設計思想是:定義兩個指針變量p和q,初始時均指向頭結點的下一個結點(鏈表的第一個結點),p指針沿鏈表移動;當p指針移動到第k個結點時,q指針開始與P指針同步移動;當p指針移動到最後一個結點時,q指針所指示結點爲倒數第k個結點。以上過程對鏈表僅進行一遍掃描。

2)算法的詳細實現步驟如下:
①count=0,p和q指向鏈表表頭結點的下一個結點。
②若p爲空,轉⑤。
③若count等於k,則q指向下一個結點;否則,count=count+1。
④p指向下一個結點,轉②。
⑤若count等於k,則查找成功,輸出該結點的data域的值,返回1;否則,說明k值超過了線性表的長度,查找失敗,返回0。(查k的值)
⑥算法結束。


3)算法實現
typedef int ElemType;    //鏈表數據的類型定義
typedef struct LNode{    //鏈表結點的結構定義
    ElemType data;        //結點數據
    struct Lnode *link;    //結點鏈接指針
}LNode, *LinkList;        //c知識,忘了可以回去查

int Search_k(LinkList list,int k) {  
    //查找鏈表list倒數第k個結點,並輸出該結點data域的值  
    LNode *p = list->link, *q=list->link;  //指計;p、q 指示第一個結點  
    int count=0;  
    while (p!=NULL) {  //遍歷鏈表直到最後一個結點  
        if (count<k) count++;  //計數,若 count<k 只移動 p  
        else q=q->link;  
        p-p->link;  //之後讓p、q同步移動  
    } //while  
    if(count<k)  
        return 0;  //查找失敗返回0  
    else{    //否則打印並返回1  
    printf("%d", q->data);  
    return 1;  
    }  
} //Search_k  



//先到這吧 2015-2-28 02:12  腦瓜子感覺又要擴容了 ,還有8個鏈表的逆襲必備招,看官容臣妾休息休息身子以後不定期分享~~歡迎關注(*^__^*)  GarryLin~

再次聲明,轉載請註明出處!!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章