轉載請註明: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~
再次聲明,轉載請註明出處!!!!!