本文只是对数组和链表的归并排序的代码记录,并不对算法原理进行过多的说明。并只对关键代码进行注释。
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;
}
2.数组归并排序的非递归实现
#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;
}
3.链表的插入排序
这里我用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) );
}
};