一些常見的單鏈表題目,總結思路和實現代碼。
1.單鏈表的反序
2.給單鏈表建環
3.檢測單鏈表是否有環
4.給單鏈表解環
5.檢測兩條鏈表是否相交
6.不輸入頭節點,刪除單鏈表的指定節點(只給定待刪除節點指針)
1.單鏈表的反序
- //逆轉鏈表,並返回逆轉後的頭節點
- node* reverse(node *head)
- {
- if(head == NULL || head->next == NULL)
- {
- return head;
- }
- node *cur = head;
- node *pre = NULL;
- node *tmp;
- while(cur->next)
- {
- tmp = pre;
- pre = cur;
- cur = cur->next;
- pre->next = tmp; //操作pre的next逆轉
- }
- cur->next = pre; //結束時,操作cur的next逆轉
- return cur;
- }
2.給單鏈表建環
- //給單鏈表建環,讓尾指針,指向第num個節點,若沒有,返回false
- bool bulid_looplink(node *head, int num)
- {
- node *cur = head;
- node *tail = NULL;
- int i = 0;
- if(num <= 0 || head == NULL)
- {
- return false;
- }
- for(i = 1; i < num; ++i)
- {
- if(cur == NULL)
- {
- return false;
- }
- cur = cur->next;
- }
- tail = cur;
- while(tail->next)
- {
- tail = tail->next;
- }
- tail->next = cur;
- return true;
- }
3.檢測單鏈表是否有環
- //檢測單鏈表是否有環,快慢指針
- bool detect_looplink(node *head)
- {
- node *quick_node = head->next, *slow_node = head;
- if(head == NULL || head->next == NULL)
- {
- return false;
- }
- while(quick_node != slow_node)
- {
- if(quick_node == NULL || slow_node == NULL)
- break;
- quick_node = quick_node->next->next;
- slow_node = slow_node->next;
- }
- if(quick_node != NULL && slow_node != NULL) //非尾節點相遇
- return true;
- return false;
- }
4.給單鏈表解環
ps:爲了增加節點位圖的效率,本應使用hash或則紅黑樹,這裏不造車了,直接用 set容器
- //找到有環節點,並解環,找到並解環,返回true,無環,返回false
- //思路:先找到環節點:被2個節點指向的節點(一定有環的條件)ps:不考慮中間環,因爲只有一個next節點,只可能是尾環
- bool unloop_link(node *head)
- {
- set<node *> node_bitmap; //node的地址位圖
- unsigned int num = 0;
- node *cur = head, *pre = NULL;
- while(cur != NULL)
- {
- if(!node_bitmap.count(cur) ) //該節點未被遍歷過
- {
- node_bitmap.insert(cur);
- ++num;
- }
- else //指向已被遍歷過的節點,此時pre節點爲尾節點
- {
- pre->next = NULL;
- return true;
- }
- pre = cur;
- cur = cur->next;
- }
- return false;
- }
5.檢測兩條鏈表是否相交
- //檢測兩條鏈表是否相交,是則返回第一個交點,否則返回NULL
- //思路:把2個鏈表各遍歷一遍,記下長度length1和length2,若2者的尾節點指針相等,則相交。
- // 之後再把長的鏈表從abs(len1-len2)的位置開始遍歷,第一個相等的指針爲目標節點
- node* detect_intersect_links(node *first_link, node *second_link)
- {
- int legnth1 = 1, length2 = 1, pos = 0;
- node *cur = NULL, *longer_link = first_link, *shorter_link = second_link;
- if(first_link == NULL || second_link == NULL)
- {
- return NULL;
- }
- while(first_link->next || second_link->next) //遍歷2個鏈表
- {
- if(first_link->next)
- {
- first_link = first_link->next;
- ++legnth1;
- }
- if(second_link->next)
- {
- second_link = second_link->next;
- ++length2;
- }
- }
- if(first_link != second_link) //比較尾節點
- {
- return NULL;
- }
- pos = legnth1 - length2;
- if(legnth1 < length2) //保證 longer_link爲長鏈表
- {
- pos = length2 - legnth1;
- cur = longer_link;
- longer_link = shorter_link;
- shorter_link = cur;
- }
- while(pos-- > 0)
- longer_link = longer_link->next;
- while(longer_link || shorter_link)
- {
- if(longer_link == shorter_link) //找到第一個交點
- {
- return longer_link;
- }
- longer_link = longer_link->next;
- shorter_link = shorter_link->next;
- }
- return NULL;
- }
6.不輸入頭節點,刪除單鏈表的指定節點(只給定待刪除節點指針)
- //無頭節點,隨機給出單鏈表中一個非頭節點,刪除該節點,當傳入空節點,或者尾節點時,返回false
- //思路:由於沒有頭節點,非循環單鏈表,無法獲取目標節點的前節點,所以只能把它的next節點數據前移,並刪除next節點
- //ps:當傳入節點爲尾節點,無法用此方法刪除
- bool withouthead_delete_node(node *target_node)
- {
- node *cur = NULL;
- if(target_node == NULL || target_node->next == NULL) //空節點或者尾節點,失敗
- {
- return false;
- }
- cur = target_node->next;
- target_node->name = cur->name;
- target_node->next = cur->next;
- delete cur;
- return true;
- }