链表归并排序

来源:互联网 发布:手机游戏加速器软件 编辑:程序博客网 时间:2024/05/29 11:51
#include <iostream>using namespace std;/*** 对链表进行原地排序* 回忆数组归并最重要的就是:找到数组中点,以及归并两个有序数组。* 类似地这里有两个关键点: * (1)找到链表的中间节点,用一快一慢两个指针往前走;* (2)归并两个已经排好序的链表,指向归并结果的指针总是变化的,所以需要返回一个指向归并好的链表的头指针;* (3)最后注意,将链表划分成两截的时候,还应该让前半部分的最后一个节点指向空(截断),这样递归各自部分就不需要还去*   指明到哪个节点结束了。*/typedef struct node{int value;struct node *next;}NODE;void printList(NODE *head);NODE *merge(NODE *a, NODE *b);void splitList(NODE *head, NODE **list1, NODE **list2);void mergeSort(NODE **headRef);/*** 算法主体:找到中间节点,截断,各自递归,再将两部分归并,同时记录归并后的头指针*/void mergeSort(NODE **headRef){NODE *head = *headRef;NODE *a,*b;//当只剩下一个节点或者没有节点的时候不需要继续归并if(head == NULL || head->next == NULL) return;//将链表等长截断为两个splitList(head, &a, &b);//递归mergeSort(&a);mergeSort(&b);//归并*headRef = merge(a, b);}/*** 找到当前链表head的中间节点,并将链表截断* 前半部分通过list1返回,后半部分通过list2返回*/void splitList(NODE *head, NODE **list1, NODE **list2){NODE *p,*q;p = head;q = head->next;//没有或者只有一个节点if(head == NULL || head->next == NULL){*list1 = head;*list2 = NULL;}else{//一快一慢直到快指针走完链表while(q != NULL){q = q->next;if(q != NULL){p = p->next;q = q->next;}}//返回两半各自头指针*list1 = head;*list2 = p->next;//截断p->next = NULL;}}/*** 归并两个有序链表,采用递归方式解决(很明显有子问题)*/NODE *merge(NODE *a, NODE *b){NODE *head;if(a == NULL && b == NULL) return NULL;if(a == NULL) return b;if(b == NULL) return a;if(a->value < b->value){head = a;head->next = merge(a->next, b); //递归}else{head = b;head->next = merge(a, b->next); //递归}return head;}int main(){int a[] = {3,5,1,1,6,12,2,7,9,10,14,12,12,3,9};NODE *head,*p;//创建链表头p = (NODE *)malloc(sizeof(NODE));p->value = a[0];p->next = NULL;head = p;//构建链表for(int i=1;i<15;i++){p = (NODE *)malloc(sizeof(NODE));p->value = a[i];p->next = head->next;head->next = p;}//开始归并排序p = head;while(p->next != NULL) p = p->next;mergeSort(&head);//打印结果p = head;while(p->next != NULL){cout<<p->value<<",";p = p->next;}cout<<endl;return 0;}/*** 打印链表*/void printList(NODE *head){NODE *p = head;if(head == NULL) return;while(p->next != NULL){cout<<p->value<<",";p = p->next;}cout<<endl;}


原创粉丝点击