資料結構之快慢指標查詢連結串列中間結點
阿新 • • 發佈:2018-10-31
單鏈表是一種十分常見和應用廣泛的資料結構,也是面試題經常會問到的一個。近期複習單鏈表,就將這個單鏈表常見的考點順便複習了一遍。
面試題:如何最快的獲取單鏈表的中間節點的位置?
一般思路,從頭節點開始一個一個元素去遍歷,而後確定連結串列的長度。然後又從頭開始遍歷單鏈表,並且進行計數。當計數到達單鏈表長度一半的位置即為單鏈表的中間節點。
高階思路,設定兩個指標,步長分別為1和2.即為慢和快指標。當快指標指向連結串列的末尾時,慢結點剛好位於連結串列的中間位置。直接進行返回即可獲得連結串列的中間節點。
相關示例程式碼如下:
// // main.cpp // 快速查詢連結串列的中間節點 // // #include <iostream> using namespace std; // 演算法思想,採用快慢兩個指標,同時從指標的頭節點開始遍歷。快指標每次一動2個結點,慢指標每次移動一個結點。經過L/2次移動之後就可以完成中間節點的尋找。 struct Node{ int data; Node* pNext;// 節點指標 }; typedef Node* LinkList; // 頭插法建立單鏈表 LinkList LinkedListCreatH() { Node *L; L = (Node *)malloc(sizeof(Node)); //申請頭結點空間 L->pNext = NULL; //初始化一個空連結串列 int x; //x為連結串列資料域中的資料 cout<<"請輸入資料"<<endl; while(scanf("%d",&x) != EOF) { Node *p; p = (Node *)malloc(sizeof(Node)); //申請新的結點 p->data = x; //結點資料域賦值 p->pNext = L->pNext; //將結點插入到表頭L-->|2|-->|1|-->NULL L->pNext = p; } return L; } // 插入節點 void Insert(LinkList L,Node* node,int index){ int i = 0; Node* ptemp = L; while (i < index&&ptemp->pNext != NULL) {// 找到節點 ptemp = ptemp->pNext; i++; } node->pNext = ptemp->pNext; ptemp->pNext = node; } // 遍歷單鏈表 void printList(LinkList L){ while (L != NULL) { cout<<L->data<<endl; L = L->pNext; } } // 尋找單鏈表的中間節點 void findMinNode(LinkList L){ Node* pNode = L; while (L != NULL&&pNode->pNext !=NULL) { L = L->pNext; pNode = pNode->pNext; pNode = pNode->pNext; } cout<<"中間節點為:"<<L->data<<endl; } int main(int argc, const char * argv[]) { // insert code here... std::cout << "Hello, World!\n"; LinkList m_list = LinkedListCreatH(); Node tempData; tempData.data = 9; Insert(m_list, &tempData, 4); printList(m_list); findMinNode(m_list); return 0; }
最後獲得單鏈表的中間節點為4.當然,快慢指標還可以用於判斷一個單鏈表是否存在環以及兩個單鏈表是否相交等場景。