归并排序:
1. 思路
分割->合并。
合并的时候,每次选择较小的,达到排序效果。归并排序时一稳定排序.
需要掌握好数组实现的排序算法,链表实现的排序算法,手动排序过程。
数组实现:
int c[2000]; //数组实现:合并时候需要辅助空间
void Merge(int a[], int begin, int mid, int last)
{
int i = begin; //【begin,mid】的指针
int j = mid + 1; //【mid+1,last】的指针
int tmp = 1;
while(i<=mid && j<=last )
{
if (a[j]<a[i])
c[tmp++] = a[j++]; // 这里还可以求数组的逆序数: num += mid-i+1
else
c[tmp++] = a[i++];
}
while(j<=last)
c[tmp++] = a[j++];
while(i<=mid)
c[tmp++] = a[i++];
for (i=begin;i<=last;i++) //复制
a[i] = c[i-begin+1];
}
void MergeSort(int a[], int begin,int last)
{
if (last>begin)
{
int mid = (begin+last)/2;
MergeSort(a,begin,mid);
MergeSort(a,mid + 1,last);
Merge(a,begin, mid,last);
}
}
链表实现:
void mergesort(Node<int> *&head)
{
//1.分割:找到中间节点. (两个指针,一个用2倍速度向前移动即可)
//2.排序:递归排序
//3.归并:合并,链表操作
if(head->next==NULL)
return;
Node<int> *middle=divide_from(head); //分割函数,考虑中间节点
mergesort(head);
mergesort(middle);
head = merge(head,middle); //合并函数,考虑顺序
}
Node<int>* divide_from(Node<int> *first)
{
Node<int> *position;
Node<int> *midpoint;
Node<int> *second_half;
midpoint = first;
if(midpoint == NULL)
return NULL;
position = midpoint->next;
while(position != NULL)
{
position = position->next;
if(position != NULL)
{
midpoint = midpoint->next;
position = position->next;
}
}
second_half = midpoint->next;
midpoint->next = NULL;
return second_half;
}
Node<int> * merge(Node<int> *first,Node<int> *second)
{
Node<int> *last_sorted; //point the last node of the list
Node<int> temp; //定义了一个空的结点,没有作用,但对于过渡指针起着很好的作用.在以后的编程中也可以适当采用这样的方法.
last_sorted = &temp;
while(first != NULL && second != NULL)
{
if(first->data <= second->data)
{
last_sorted->next = first;
last_sorted = first;
first = first->next;
}
else
{
last_sorted->next = second;
last_sorted = second;
second = second->next;
}
}
if(first == NULL)
{
last_sorted->next = second;
}
else
{
last_sorted->next = first;
}
return temp.next;//这里证明了结点temp只是一个过渡的作用,需要的是指针而已.
}