代碼的魯棒性:鏈表的倒數第 k 個節點

題目:輸入一個鏈表,輸出該鏈表中倒數第 k 個節點。爲了符合大多數人的習慣,本題從 1 開始計數,即鏈表的尾節點是倒數第一個節點。ios

    爲了獲得倒數第 k 個節點,很天然的想法就是:首先走到鏈表的尾端回溯 k 步。然而,單向鏈表的節點只有從前向後的指針,沒有從後往前的指針,這種思路是行不通的。spa

    既然不能從尾節點遍歷單鏈表,咱們仍是把思路回到單鏈表的頭結點。假設整個鏈表有 n 個節點,那麼倒數第 k 個節點就是,從頭開始的第 n - k + 1 個節點。如何得知整個鏈表的節點數目? 只要從頭遍歷鏈表,每通過一個節點,計數器加 1 便可。也就是說,這種方法須要遍歷兩次單鏈表。第一次,統計鏈表中的節點數目; 第二次,就可以找到倒數第 k 個節點。指針

    3)若是要求只能遍歷一次單鏈表。咱們能夠定義兩個指針。第一個指針從鏈表的頭指針開始遍歷向前走 k - 1 步,第二個指針保持不動;從第 k 步開始,第二個指針也從單鏈表的頭指針開始遍歷,兩個指針始終保持 k - 1,當第一個指針走到(走在前面的指針)鏈表的尾節點時,第二個指針(走在後面的)正好指向的是鏈表的倒數第 k 個節點。【使用的是快慢指針】內存

寫代碼時存在的三個潛在的風險:ci

    1)輸入的頭指針爲 NULL的時候,因爲代碼會試圖訪問空指針指向的內存,程序會崩潰io

    2)當輸入的頭指針所指向的單鏈表的結點個數不足 k 個的時候。因爲在for 循環中,程序會向前中 k - 1 步,程序就會崩潰。stream

    3)輸入的參數爲 k 爲 0,因爲k 是一個無符號整數,那麼在 for 循環中 k - 1 將獲得的不是 -1,所以 for 循環的次數遠遠超乎咱們的想象,一樣會形成程序的崩潰。List

//輸入一個鏈表,輸出鏈表的倒數第 k 個節點[使用兩個指針:快慢指針]
#include<iostream>
using namespace std;
循環

typedef int ElemType;
typedef struct LNode
{
 ElemType data;
 struct LNode *next;
}ListNode, *LinkList;
遍歷

LinkList CreateLinkList(LinkList L)
{
 if(L == NULL)
 {
  L = new LNode();
  L->next = NULL;
 }
 return L;
}
void InsertLinkList(LinkList L, ElemType value)
{
 if(L == NULL)
  return;
 LNode *p, *s;
 s = L;

 p = new LNode();
 p->data = value;
 p->next = s->next;
 s->next = p;
}

LNode* FindKthToTail(LinkList L, int k)
{
 if(L == NULL || k == 0)  //鏈表爲空或者輸入的 k 不合法時,返回NULL
  return NULL;
 LNode *pNode = L;
 LNode *pBegin = NULL;
 for(int i = 0; i < k - 1; i++)
 {
  if(pNode->next != NULL)  //若是第一個指針指向的下一個元素不爲空時,則向後移動第一個指針
   pNode = pNode->next;
  else
   return NULL;   //不然,返回NULL,此時說明,單鏈表的節點數目不足 k 個
 }
 pBegin = L;
 while(pNode->next != NULL)  //移動第一個指針,直至第一個指針指向最後一個節點
 {
  pNode = pNode->next;
  pBegin = pBegin->next;  //移動第二個指針
 }
 return pBegin;     //返回第二個指針,其指向的正是倒數第 k 個節點
}

int main()
{
 LNode *L, *result;
 L = NULL;
 result = NULL;
 L = CreateLinkList(L);
 int value;
 while(cin >> value)
 {
  InsertLinkList(L, value);
 }
 result = FindKthToTail( L, 1);
 cout << result->data << endl;

 system("pause");
 return 0;
}

 

    相關題目:

    1)求鏈表的中間節點:若是鏈表的節點總數爲奇數,返回中間節點;若是節點的總數爲偶數,則返回中間兩個節點中的任意一個。【解決該問題,也能夠定義兩個指針,同時從鏈表的頭結點開始出發,第一個指針一次走一步,第二個指針一次走兩步。當第二個指針走到鏈表的末尾的時候,走得慢的指針正好走到鏈表的中間。】

    2)判斷一個單鏈表是否造成了一個環形結構【一樣的定義兩個指針,同時從鏈表的頭結點開始出發,一個指針一次走一步,另外一個指針一次走兩步。若是走的快的指針追上了走得慢的指針,則說明鏈表是環形的。若是走得快的指針走到了鏈表的末尾都沒有追上走得慢的指針,則說明鏈表不是環形的。】

相關文章
相關標籤/搜索