归并算法时间复杂度:O(NlogN)
注意:断链和合并的思想
两个链表的归并:
#include<stdio.h>
#include<stdlib.h>
typedef struct listNode{
int val;
struct listNode* next;
}ListNode;
ListNode* mergeNode(ListNode* left, ListNode* right) {
if(left == NULL) {
return right;
}
if(right == NULL) {
return left;
}
//如果左边值比右值大,将将右链接到左链后边
if(left->val < right->val) {
left->next = mergeNode(left->next, right);
return left;
}else { 如果左边值比右值,将将左链接到右链后边
right->next = mergeNode(left, right->next);
return right;
}
}
ListNode* sortList(ListNode* head){
ListNode *fastNode,*slowNode,*breakNode,*left,*right;
if(head == NULL || head->next == NULL) {
return head;
}
//找中间位置元素进行合并
fastNode = head;
slowNode = head;
breakNode = head;
//整个思想很有意思,可以保证slowNode始终处在中间的位置,breakNode处于断链的位置
while(fastNode && fastNode->next) {
fastNode = fastNode->next->next;
breakNode = slowNode;
slowNode = slowNode->next;
}
breakNode->next = NULL;
left = sortList(head);
right = sortList(slowNode);
//采用分治法将左右节点排序
mergeNode(left, right);
}
int main(){
int i ;
ListNode *LN,*p,*LTemp;
int w[4] ={4,2,1,3};
LN = (ListNode *)malloc(sizeof(ListNode));
p = LN;
p->val = w[0];
p->next = NULL;
for(i = 1; i< 4; i++){
LTemp= (ListNode *)malloc(sizeof(ListNode));
LTemp->val = w[i];
LTemp ->next =NULL;
p->next = LTemp;
p= LTemp;
}
LN= sortList(LN);
while(LN){
printf("%d ",LN->val);
LN= LN->next;
}
printf("\n");
return 0;
}
K个有序链表的归并排序:
//合并多个链表,采用归并的思想,将链表数组对半归并,不产生新链表,直接节点
//先是合并两个链表
struct ListNode* mergeTwoLists(struct ListNode* L1, struct ListNode* L2){
if(L1 == NULL) {
return L2;
}
if(L2 == NULL) {
return L1;
}
//如果左边值比右值大,将将右链接到左链后边
if(L1->val < L2->val) {
L1->next = mergeTwoLists(L1->next, L2);
return L1;
}else { 如果左边值比右值,将将左链接到右链后边
L2->next = mergeTwoLists(L1, L2->next);
return L2;
}
}
//第二种方式归并
//先是合并两个链表
struct ListNode* mergeTwoLists(struct ListNode* L1, struct ListNode* L2){
struct ListNode head;
if(!L1) return L2;
if(!L2) return L1;
//如何保证头节点不发生改变
head.next = L1;
//将L1指向head,这样比较时L1 ->next 就i是原来L1的第一个节点
L1 = &head;
//将L2接到L1后边,遍历L2
while( L2 != NULL){
//保存L1后边的节点
struct ListNode *p = NULL;
struct ListNode *q = NULL;
p = L1->next;
q = L2 ->next;
//合并L1和L2
if(L1->next == NULL){
L1 ->next = L2;
break;
}
if(p->val >= L2->val){
L1->next= L2;
L2 ->next = p;
L2 = q;
}
L1 =L1 ->next;
}
return head.next;
}
//分开一个链表
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize){
struct ListNode *L1, *L2;
int mid;
if(listsSize == 0){
return NULL;
} else if(listsSize ==1)
{
return lists[0];
}
else if(listsSize == 2) {
return mergeTwoLists(lists[0], lists[1]);
}
mid = (listsSize+1)/2;
L1 = mergeKLists(&lists[0],mid);
L2 = mergeKLists(&lists[mid],listsSize - mid);
return mergeTwoLists(L1, L2);
}