/**
* 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));
}