排序算法详解<3>

着里说两种,用二叉树的性质来表示的排序方法,分别是堆排序和归并排序。

  1. 堆排序
    堆排序就是利用堆(假设利用大顶堆)进行排序的方法。他的基本思想是,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根结点。将它移走(其实就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后将剩余的n-1个序列从新构造成一个堆,这样就会得到n个元素中的次小值。如此反复执行,便能得到一个有序序列了。
    图示为:
    在这里插入图片描述代码示例:
//堆排序
void HeapAdjust(int *a, int s, int m)
{
 int temp, j;
 temp = a[s];
 for (j = 2 * s; j <= m; j *= 2)//沿关键字较大的孩子结点向下筛选 
 {
  if (j < m && a[j] < a[j + 1])
   ++j;      //j为关键字中较大的记录的下标
  if (temp >= a[j])
   break;
  a[s] = a[j];
  s = j;
 }
 a[s] = temp;
}
void HeapSort(int* a,int len)
{
 int i;
 for (i = len / 2; i > 0; i--)//把当前序列排序为大顶堆
 {
  HeapAdjust(a, i, len);
 }
 for (i = len-1; i > 0; i--)
 {
  Swap(&a[0], &a[i]);//将堆顶记录和当前子序列的最后一个元素交换
  HeapAdjust(a, 0, i - 1);//把除最后一个元素的子序列从新调整为大顶堆
 }
}

堆排序是一种不稳定的排序算法,它的时间复杂度为O(n㏒n),空间复杂度为O(1).

  1. 归并排序
    归并排序就是利用归并的思想实现的排序算法。它的原理是假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到(n/2)(【x】表示不小于x的最小整数)个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
    图示为:
    在这里插入图片描述
    代码表示为:
//归并排序
void merge(int* src, int* des, int low, int high, int mid)
{
 int i = low;
 int k = low;
 int j = mid + 1;
 while ((i <= mid) && (j <= high))
 {
  //排序,把小的依次放入des数组中
  if (src[i] < src[j])
  {
   des[k++] = src[i++];
  }
  else
  {
   des[k++] = src[j++];
  }
 }
 while (i <= mid)
 {
  des[k++] = src[i++];
 }
 while (j <= high)
 {
  des[k++] = src[j++];
 }
}
void M_Sort(int* src, int* des, int low, int high, int max_size)
{
 int mid = (low + high) / 2;
 //判断此时每个小块中的元素是否为1个;
 if (low == high)
 {
  des[low] = src[low];
 }
 else
 {
  int mid = (low + high) / 2;
  int* des_space = (int*)malloc(sizeof(int)*max_size);
  if(NULL != des_space)
  {
   //递归分:把一个数组不断从中分开 ,直到分为一个元素一个快
   M_Sort(src, des_space, low, mid, max_size);
   M_Sort(src, des_space, mid + 1, high, max_size);
   //合并,把分开的元素按反向合并,并排序
   merge(des_space, des, low, high, mid);
  }
  free(des_space);//释放用malloc开辟的空间
 }
}
void Merge_Sort(int* a, int low, int high, int len)
{
 M_Sort(a, a, low, high, len);
}

归并排序是一个稳定的排序算法,在归并排序中,大部分工作是在解决/归并的步骤中完成的,因为分解步骤并没有真正执行任何操作(视为O(1))。
当我们称之为归并的(a,低,中,高)时候,我们处理k =(高 - 低+ 1)项。 最多会有 k-1 个比较。 从原始数组 a 到临时数组 b 有 k 个移动,而另一个 k 移回。 总的来说,归并子例程内的操作次数 <3k-1 = O(k)。
主函数再次不做解释,自己根据自己的要求自己写主函数;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值