各种排序算法(2)——二路归并,堆排序

排序属于最基础的,唉!必须熟练掌握啊

#include <iostream>
#include <stdio.h>
#include <stack>
using namespace std;
const int MaxSize=100;
int b[MaxSize]; //归并排序中的辅助数组b
//类似于两个有序链表的合并
void Merge(int *a,int left,int mid,int right)
{
 int i,j,k;
 for(i=left;i<=right;i++)
  b[i]=a[i];
 for(i=left,j=mid+1,k=i;(i<=mid)&&(j<=right);k++)
 {
  if(b[i]<=b[j])
   a[k]=b[i++];
  else
   a[k]=b[j++];
 }
 while(i<=mid)
  a[k++]=b[i++];
 while(j<=right)
  a[k++]=b[j++];
}
void MergeSort(int *a,int left,int right)
{
 if(left<right)
 {
  int mid=(left+right)/2;
  MergeSort(a,left,mid); //左侧子序列递归排序
  MergeSort(a,mid+1,right); //右侧子序列递归排序
  Merge(a,left,mid,right);
 }
}
//从二叉树中最后一个非页节点开始调整(向下循环调整)
void AdjustDown(int *a,int k,int len)
{
 int i;
 a[0]=a[k];               //这里a[0]作为一个辅助空间,而且为了下标从1开始便于找左右子节点
 for(i=2*k;i<=len;i*=2)
 {
  if(i<len&&a[i]<a[i+1])
  i++;                      //比较左右叶子节点,让i记录大的那个
  if(a[0]>=a[i])
   break;               //不需要调整
  else
  {
   a[k]=a[i];
   k=i; //记录下面调换节点的位置,以便继续向下筛选大的顶
  }
 }
  a[k]=a[0];
}
//初始化数据建成一个大顶堆
void BuildMaxHeap(int *a,int len)
{
 int i;
 for(i=len/2;i>0;i--)
  AdjustDown(a,i,len);
}
void HeapSort(int *a,int len)
{
 int i;
 stack<int> s;
 BuildMaxHeap(a,len);
 
 for(i=len;i>0;i--)
 {
  cout<<a[1]<<" ";          //放入栈后,再弹出即可实现由小到大输出(或建小顶堆)
  s.push(a[1]);
  a[1]=a[i];
  AdjustDown(a,1,i-1);  //这里要注意最后一个a[1]输出
  }
 cout<<endl;
 while(!s.empty())
 {
	 cout<<s.top()<<" ";
	 s.pop();
 }
}
  
int main()
{
	int i,n;
	int a[50];
 //int a[10]={0,9,5,3,1,67,45,23,11,2};
	cin>>n;
	for(i=0;i<n;i++)
	 cin>>a[i];
  HeapSort(a,n-1);      //这里注意a[0]是辅助空间,可以随便输个值,length要比实际数组小1
  cout<<endl;
 return 0;
}

归并排序对初始序列不敏感,时间复杂度O(nlogn),空间复杂度是O(n);建堆的时间复杂度是O(n),堆排序总体是O(nlogn),空间复杂度是O(1).

你可能感兴趣的:(归并排序,堆排序)