/**
* Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.
For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.
分为四步。
第一步找到链表长度。
第二步把链表从中间分为两个子链表。
第三步反转第二个子链表(ReverseLinkedList中的Reverse函数)。
第四步把第二个子链表Merge到第一个子链表里面。
*/
// // ReorderList.c // Algorithms // // Created by TTc on 15/6/22. // Copyright (c) 2015年 TTc. All rights reserved. // /** * Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… You must do this in-place without altering the nodes' values. For example, Given {1,2,3,4}, reorder it to {1,4,2,3}. 分为四步。 第一步找到链表长度。 第二步把链表从中间分为两个子链表。 第三步反转第二个子链表(ReverseLinkedList 中的Reverse函数)。 第四步把第二个子链表Merge到第一个子链表里面。 */ #include "ReorderList.h" #include <stdbool.h> #include <stdlib.h> #include "List.h" /********************************************************************/ // LeetCode /********************************************************************/ struct ListNode { int val; struct ListNode *next; }; //双指针大法 链表反转函数(请背熟练) /*Since only constant memory is allowed, time cost is O(k) */ static struct ListNode* Reverse(struct ListNode *begin, struct ListNode *end){ struct ListNode* prev = begin->next; struct ListNode* curr = prev->next; while(curr != end){ prev->next = curr->next; curr->next = begin->next; begin->next = curr; curr = prev->next; } return prev; } void reorderList(struct ListNode* head) { if (head == NULL) return; //Step1: 第一步找到链表长度。 struct ListNode *tmp = head; int len = 0; while (tmp != NULL) { tmp = tmp->next; ++len; } int num_insertion = (len-1)/2; //Step2: 第二步把链表从中间分为两个子链表。 tmp = head; int count = 0; while (count < len-1-num_insertion) { tmp = tmp->next; ++count; } struct ListNode *second_half = tmp->next; tmp->next= NULL; //Step3: 第三步反转第二个子链表(ReverseLinkedList 中的Reverse函数)。 if (second_half != NULL && second_half->next != NULL) { struct ListNode *dummyHead = (struct ListNode *)malloc(sizeof(*dummyHead)); dummyHead->next = second_half; Reverse(dummyHead, NULL); second_half = dummyHead->next; } //Step4: 第四步把第二个子链表Merge到第一个子链表里面。(隔槽插入) struct ListNode *first_half = head; while (second_half != NULL) { struct ListNode *temp1 = second_half->next; second_half->next = first_half->next; first_half->next = second_half; second_half = temp1; first_half = first_half->next->next; } } /********************************************************************/ /********************************************************************/ /********************************************************************/ // List.c 是范性类 单链表 /********************************************************************/ //反转单链表中 begin 到 end 节点 (如果是反转整个 单链表 则需要传 0,list_size(),需要创建一个虚拟头节点) static ListElmt* tt_Reverse(ListElmt *begin, ListElmt *end){ ListElmt* prev = begin->next; ListElmt* curr = prev->next; while(curr != end){ prev->next = curr->next; curr->next = begin->next; begin->next = curr; curr = prev->next; } return prev; } void tt_reorderList(ListElmt* head) { if (head == NULL) return; //Step1: 第一步找到链表长度。 ListElmt *tmp = head; int len = 0; while (tmp != NULL) { tmp = tmp->next; ++len; } int num_insertion = (len-1)/2; //Step2: 第二步把链表从中间分为两个子链表。 tmp = head; int count = 0; while (count < len-1-num_insertion) { tmp = tmp->next; ++count; } ListElmt *second_half = tmp->next; tmp->next= NULL; printf("second_half======>%d\n", *(int *)second_half->data); print_listNode(second_half); //Step3: 第三步反转第二个子链表(ReverseLinkedList 中的Reverse函数)。 if (second_half != NULL && second_half->next != NULL) { ListElmt *dummyHead = (ListElmt *)malloc(sizeof(*dummyHead)); dummyHead->next = second_half; ListElmt * result = tt_Reverse(dummyHead, NULL); printf("result======>%d\n", *(int *)result->data); second_half = dummyHead->next; print_listNode(second_half); } //Step4: 第四步把第二个子链表Merge到第一个子链表里面。(隔槽插入) ListElmt *first_half = head; while (second_half != NULL) { ListElmt *temp1 = second_half->next; second_half->next = first_half->next; first_half->next = second_half; second_half = temp1; first_half = first_half->next->next; } } void test_tt_reorderList(){ List l1; list_init(&l1, free); int *data ; int array[15] = {10,9,8,7,6,5,4,3,2,1}; // for (int i = 0; i< 10; i++) { for (int i = 0; i< 10; i++) { if ((data = (int *)malloc(sizeof(int))) == NULL) return ; *data = array[i]; if (list_ins_next(&l1, NULL, data) != 0) //逐个插入元素 return; } print_list(&l1); tt_reorderList(list_head(&l1)); printf("反转后*****************\n"); print_listNode(list_head(&l1)); }