資料結構面試之一——單鏈表常見操作

來源:互聯網
上載者:User
資料結構面試之一——單鏈表常見操作

題註:《程式員面試寶典》有相關習題,但思路相對不清晰,排版有錯誤,本文對此參考相關書籍和自己觀點進行了重寫,供大家參考。

1.尋找鏈表元素

Step1:置尋找標記bfound=false;判斷鏈表是否為空白,是,提示“不能尋找空鏈表”;否,進入step2。

Step2:從鏈表頭開始尋找,判斷(當前點的info是否與待尋找元素值相等&&指標未指向末尾),是,“尋找結束,bfound=true”,否,繼續尋找。

Step3:判斷bfound= = true,是,“提示尋找成功”,否,“提示尋找失敗”。

/尋找單鏈表元素template<typename Type>void linkedlistType<Type>::search(const Type& searchItem){       nodeType<Type> *current;       bool found = false;        if(first == NULL)                                          //1.空鏈表       {              cout << "WARNING: Can not search an empty list!" << endl;              return;       }       else       {              current = first;              while(!found && current != NULL)              {                     if(current->info == searchItem)                     {                            found = true;                            break;                     }                     else                     {                            current = current->link;                     }              }              if(found)              {                     cout << searchItem << " was found in the List! " << endl;              }              else              {                     cout << searchItem << " was not found in the List! " << endl;              }       }}

2.刪除鏈表元素值

Step1:置尋找標記bfound=false; 判斷鏈表是否為空白,是,提示“不能對空鏈表進行刪除操作”;否,進入step2。

Step2:判斷待刪除元素值是否與前端節點元素值相等,是,調整前端節點指標;否,進入step3。

Step3:判斷鏈表中是否存在該元素,否,“提示元素不存在”;是,進入step4。

Step4:判定要刪除元素是否與末尾節點元素值相等,是,調整末尾last指標;否,此時為中間節點,需要調整trailCurrent和Current指標的指向。

//刪除單鏈表元素template<typename Type>void linkedlistType<Type>::deleteNode(const Type& deleteItem){       nodeType<Type> *tempNode = new nodeType<Type>;       nodeType<Type> *current = new nodeType<Type>;       nodeType<Type> *trailCurrent = new nodeType<Type>;       bool found;             //鏈表為空白 case1       if(first == NULL)       {              cout << "Can not delete an empty List!" << endl;       }       else       {              if( first->info == deleteItem )              {                     //要刪除的也是第一個節點(僅一個節點,或不止一個節點) case2                     tempNode = first;                     first = first->link;                     if(first == NULL)                     {                            last = NULL;                     }                                              delete tempNode;              }              else              {                     //先尋找,後判斷... case3                     found = false;                     trailCurrent = first;                     current = first->link;                      while((!found) && (current != NULL))                     {                            if(deleteItem  != current->info)                            {                                   trailCurrent = current;                                   current = current->link;                            }                            else                            {                                   found = true;                            }                     }                      if(found)                     {                            //能找到...                            trailCurrent ->link = current->link;                             if(current == last)                            {                                   last = trailCurrent; //case 3a                            }                            delete current;         //case 3b                     }                     //不存在該點...case4                     else                     {                            cout << "The deleteItem is not Exist in the List! " << endl;                     } //end else              }//end else       }//end else      }// end deleteNode

3.單鏈表逆置[迭代實現]

Step1:判斷鏈表是否為空白,是,提示“不能對空鏈表進行逆置操作“;否,進入Step2;

Step2:從第2個節點開始,依次將每個節點插入到第一個節點的前面,判斷指標是否指向了鏈表尾部,是,返回頭指標結束;否,繼續迭代後面的鏈表元素。

template<typename Type>nodeType<Type>* linkedlistType<Type>::reverseList()   //逆置單鏈表{       if(first == NULL)       {              cout << "Can't reverse empty List!" << endl;       }       else       {              nodeType<Type>* p = first;              nodeType<Type>* q = p->link;               while(q != NULL)              {                     p->link = q->link;                     q->link = first;                     first = q;                     q = p->link;              }       }       return first;}

4.單鏈表排序[直接插入排序]

思路:分為以下幾種情況:

1)  單鏈表為空白;

2)  單鏈表非空,但僅含一個元素,無需排序已經有序;

3)  待插入元素小於頭結點的元素;

4)  待插入元素為前已有序的中間的元素值;

5)  待插入的元素前所有元素都比其小,直接插到末尾。

分別用lastInOrder記錄已經有序的最後一個節點,firstOutOfOrder第一個尚未排序(正待參與)排序的節點。current用於記錄迴圈的節點,trailCurrent記錄current前的節點。

template<typename Type>void linkedlistType<Type>::sortList()     //單鏈表排序{       nodeType<Type>* current;       nodeType<Type>* trailCurrent;       nodeType<Type>* lastInOrder;       nodeType<Type>* firstOutOfOrder;        lastInOrder = first;        //case1,表為空白.       if(first == NULL)       {              cout << "Can't Sort of empty List!" << endl;              return;       }        //case2,表不為空白,但表長為1,僅含1個元素.       if(first->link == NULL)       {              cout << "The List Was Already ordered!" << endl;              return;       }        while(lastInOrder->link != NULL)       {              firstOutOfOrder = lastInOrder->link;                  //case3,要插入的元素小於第1個元素.              if(firstOutOfOrder->info < first->info)              {                     lastInOrder->link = firstOutOfOrder->link;                     firstOutOfOrder->link = first;                     first = firstOutOfOrder;              }              else              {                         trailCurrent = first;                     current = first->link;                     while(current->info < firstOutOfOrder->info)                     {                            trailCurrent = current;                            current = current->link;                     }                      //case4,要插入的元素在前已有序元素的中間.                     if(trailCurrent != lastInOrder)                     {                            lastInOrder->link = firstOutOfOrder->link;                            firstOutOfOrder->link = current;                            trailCurrent->link = firstOutOfOrder;                     }                     else                     {                            //case5,要插入的元素大於最後一個已經有序的元素.                            lastInOrder = lastInOrder->link;                     }//end else              }//end else       }//end while}

5.單鏈表在不知道鏈表長度的前提下求鏈表中間節點的值。

思路:分以下幾種情況:

1)  鏈表為空白;

2)  鏈表非空,但僅有一個或兩個節點;可以直接返回第一個節點的元素值。

3)  鏈表非空,但含有三個或三個以上的節點,可以通過定義兩個指標,一個指標的跳步為2次的時候,另一個指標的跳步為1次,當跳至結尾時,另一個節點恰好在中間位置。

//不知道表長的前提下求單鏈表中間元素

template<typename Type>Type linkedlistType<Type>::midValOfList()         {       nodeType<Type> *current;       nodeType<Type> *halfCurrent;        if(first == NULL)                                //case1,沒有節點       {              cout << "鏈表為空白!" << endl;              return -1;       }       else if(first->link == NULL || first->link->link == NULL) //case2,僅一個節點或兩個節點.       {              return first->info;       }       else                                   //case3,含有三個或三個以上的節點.       {              current = first;              halfCurrent = current;               while(current->link != NULL)              {                     current = current->link;                     if(current->link != NULL)                     {                            if(current->link != NULL)                            {                                   halfCurrent = halfCurrent->link;                                   current = current->link;                            }//end if                     }              }//end while              return halfCurrent->info;       }//end else}

6.單鏈表建立

思路:單鏈表的建立可分為根據插入新節點的位置的不同而分為兩種,1:在鏈表末尾插入元素的建立方式;2:在鏈表前面插入元素建立鏈表的方式。

對應1末尾插入分為兩步:

Step1:如果當前鏈表為空白,則置first=last=newNode;否則,進入Step2。

Step2:插入新結點元素,修改last指標。

對於2鏈表first指標前插入:主要需要保證插入元素後,修正first節點即可。

//正向末尾插入template<typename Type>nodeType<Type>* linkedlistType<Type>::buildListForward(){       nodeType<Type>  *newNode;        int num;       cout << " Enter a list of integer end with -999. " << endl;       cin >> num;       while(num != -999)       {              //..add              newNode = new nodeType<Type>;              newNode->info = num;              newNode->link = NULL;               if(first==NULL)              {                     first = newNode;                     last = newNode;              }              else              {                     last->link = newNode;                     last = newNode;              }              cin >> num;       }       return first;} //反向表頭插入,從前面插入...template<typename Type>nodeType<Type>* linkedlistType<Type>::buildListBackward(){       nodeType<Type>  *newNode;        int num;       cout << " Enter a list of integer end with -999. " << endl;       cin >> num;       while(num != -999)       {              //..add              newNode = new nodeType<Type>;              newNode->info = num;              newNode->link = first;              first = newNode;              cin >> num;       }       return first;}

7.單鏈表的測量長度

思路:鏈表的長度等效為節點個數,指標非空則迴圈判斷即可。

//求解鏈表長度template<typename Type>int linkedlistType<Type>::length(){       int count = 0;       nodeType<Type> *current;       current = first;        while(current != NULL)       {              count++;              current = current->link;       }       return count; //節點個數等效為長度.}

8.單鏈表的插入

思路:鏈表的插入也同鏈表的建立一樣分為前向、後向插入兩種形式,注意first、last指標的指向問題。

//在前面插入template<typename Type>void linkedlistType<Type>::insertFirst(const Type& newItem){       //last no use.       nodeType<Type> *newNode = new nodeType<Type>;       newNode->info = newItem;       newNode->link = first;   //在前面加入...       first = newNode;} //在後面插入元素...template<typename Type>void linkedlistType<Type>::insertLast(const Type& newItem){       nodeType<Type> *newNode = new nodeType<Type>;       newNode->info = newItem;       newNode->link = NULL;   //在後面加入...        if(first == NULL)       {              first = newNode;              last = newNode;       }       else       {              last->link = newNode;              last = newNode;       }}

後續陸續會有棧、隊列、二叉樹、圖、排序、尋找等的相關分析,希望大家關注!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.