本文只是对数组和链表的归并排序的代码记录,并不对算法原理进行过多的说明。并只对关键代码进行注释。
1.数组归并排序的递归实现(C++)
#include<iostream> using namespace std; template <typename T> void Merge(T *a,int low, int mid , int high) { T *temp = new T[high-low+1]; //申请临时缓存 int i = low , j = mid + 1 , k = 0; while( i<=mid&&j<=high) { if( a[i] <= a[j] ) { temp[k++] = a[i++]; } else { temp[k++] = a[j++]; } } while(i<=mid) { temp[k++] = a[i++]; } while(j<=high) { temp[k++] = a[j++]; } memcpy( a+low,temp,(high-low+1)*sizeof(T) ); delete temp; } template <typename T> void MergeSort(T *a,int low, int high) { if( low<high ) { int mid = ( ( high - low ) >> 1 ) + low;//定位中点 MergeSort(a,low,mid); //递归实现 MergeSort(a,mid+1,high) ; Merge(a,low,mid,high); } } template <typename T> void print(T *a , int len) { for(int i=0;i<len;i++) { cout<<a[i]<<" "; } cout<<endl; } int main() { int r[] = {10,3,5,1,9,34,54,565}; int len = sizeof(r)/sizeof(r[0]); char rr[] = {'c','a','d','h','i','b','f','g'}; MergeSort(r,0,len-1); MergeSort(rr,0,len-1); print(r,len) ; print(rr,len); system("pause"); return 0; }
#include<iostream> using namespace std; template <typename T> void Merge(T *a,int low,int mid,int high) { int i = low , j = mid + 1 , k = 0 ; T *temp = new T[high-low+1]; while( i<=mid&&j<=high) { a[i]<a[j] ? ( temp[k++] = a[i++] ):(temp[k++]=a[j++]); } while(i<=mid) { temp[k++] = a[i++]; } while(j<=high) { temp[k++] = a[j++]; } memcpy( a+low,temp,(high-low+1)*sizeof(T) ); free(temp); } template <typename T> void MergeSort(T *a,int len) { int step; //定义步长 for( step=1;step<len;step*=2 )//注意两个循环中的循环的控制条件 { int i; for( i=0;i+2*step<len;i+=2*step ) { Merge( a,i,i+step-1,i+2*step-1 ); } //剩下没能处理完的数再和前面的整体归并 if( i+step<=len-1 ) { Merge(a,i,i+step-1,len-1); } } } template <typename T> void print(T *a , int len) { for(int i=0;i<len;i++) { cout<<a[i]<<" "; } cout<<endl; } int main() { int r[] = {10,3,5,1,9,34,54,565,7}; int len = sizeof(r)/sizeof(r[0]); char rr[] = {'c','a','d','h','i','b','f','g','e'}; MergeSort(r,len); MergeSort(rr,len); print(r,len) ; print(rr,len); system("pause"); return 0; }
这里我用leetcode上面AC的代码来进行说明。
https://oj.leetcode.com/problems/insertion-sort-list/
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *insertionSortList(ListNode *head) { if( head == NULL || head->next==NULL) { return head; } ListNode *myhead = new ListNode(0);//创建头结点 myhead->next = head; ListNode *p = myhead->next; ListNode *q; ListNode *t1; while(p->next!=NULL) { if( p->next->val >= p->val ) //找到前个节点大于后个节点的指针 { p = p->next; continue; } q = p->next; p->next = p->next->next; t1 = myhead; while( t1->next->val < q->val ) //从表头开始,找到可以插入的位置 { t1 = t1->next; } q->next = t1->next; //插入节点 t1->next = q; } return myhead->next; } };
4.归并两个有序链表
https://oj.leetcode.com/problems/merge-two-sorted-lists/
非递归代码:
#include<iostream> using namespace std; struct ListNode { int val; struct ListNode *next; ListNode(int x):val(x),next(NULL) {} }; void CreateList(ListNode *&head , int *arr,int len) { head = new ListNode(arr[0]) ; ListNode *p = head; for(int i=1;i<len;i++) { ListNode *s = new ListNode(arr[i]); p->next = s; p = p->next; } } void print(ListNode *p) { if(p == NULL) return ; while(p!=NULL) { cout<<p->val<<" "; p = p->next; } cout<<endl; } //归并两个有序链表 ListNode * Merge(ListNode *l1,ListNode *l2) { ListNode *head = new ListNode(0);//关键是要创建一个头结点 ListNode *cur = head; while(l1!=NULL && l2!=NULL)//把归并的过程想清楚了,就没有问题了,代码一气呵成 { if( l1->val<l2->val ) { cur->next = l1; cur = l1; l1 = l1->next; } else { cur->next = l2; cur = l2; l2 = l2->next; } } if(l1!=NULL) cur->next = l1; if(l2!=NULL) cur->next = l2; return head->next; } int main() { int a[] = {1,3,5,7,10} ; int b[] = {-1,4,9,20}; ListNode *l1 , *l2; CreateList(l1,a,sizeof(a)/sizeof(a[0])); CreateList(l2,b,sizeof(b)/sizeof(b[0])); print(l1); print(l2); ListNode *head = Merge(l1,l2); print(head); system("pause") ; return 0; }
貌似函数里面忘记两个链表头指针判空了,但是还是过了。
递归代码:
#include<iostream> using namespace std; template <class T> class tNode { public: T val; struct tNode *next; tNode(T x):val(x),next(NULL) {} }; template <typename T> void createList(T *a,int len,tNode<T> *&head) { head = new tNode<T>(a[0]) ; tNode<T> *p = head; for(int i=1;i<len;i++) { tNode<T> *tmp = new tNode<T>(a[i]); p->next = tmp; p = tmp; } } template<typename T> void print(tNode<T> *&head) { tNode<T> *p = head; while(p!=NULL) { cout<<p->val<<" "; p = p->next; } cout<<endl; } template<typename T> tNode<T> * merge_recursive(tNode<T> *p1,tNode<T> *p2) { if( p1==NULL ) return p2; if( p2==NULL ) return p1; if( p1->val<p2->val ) { tNode<T> *tmp = merge_recursive(p1->next,p2); p1->next = tmp; return p1; } else { tNode<T> *tmp = merge_recursive(p1,p2->next); p2->next = tmp; return p2; } } int main() { tNode<int> *head1,*head2,*newhead; //int a[] = {1,3,5,7,9}; //int b[] = {2,6,8,12,14} ; int a[] = {5}; int b[] = {1,2,4}; createList( a,sizeof(a)/sizeof(a[0]),head1 ); createList( b,sizeof(b)/sizeof(b[0]),head2 ); print(head1); print(head2); bool flag = true; newhead = merge_recursive(head1,head2); print(newhead); system("pause"); return 0; }
5.链表归并排序的递归实现
其实对于链表来说,最高效的应该就是归并排序了,时间复杂度为O(nlogn),空间复杂度为O(1)。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *merge(ListNode *first,ListNode *second) { ListNode *tmp = new ListNode(0); ListNode *curr = tmp; while(first!=NULL && second!=NULL) { if(first->val <= second->val) { curr->next = first; first = first->next; } else { curr->next = second; second = second->next; } curr = curr->next; } if(first==NULL) { curr->next = second; } else if(second == NULL) { curr->next = first; } return tmp->next; } ListNode *sortList(ListNode *head) { if(head == NULL) { return head; } ListNode *first = head; ListNode *second = head; //divide the list into two equal length list while(second->next!=NULL && second->next->next!=NULL) { first = first->next; second = second->next->next; } if(first->next!=NULL) { second = first->next; first->next = NULL; first = head; } if(first==second) { return first; } return merge( sortList(first),sortList(second) ); } };