堆排序算法及其实现
大一课设题目,看吴zh老师笔记有感。。。。。。。
1.堆的定义:堆实际上是一棵完全二叉树,需要非叶节点满足的以下性质:
a[i]>=a[i*2]&&a[i]>=a[i*2+1](大根堆)
a[i]<=a[i*2]&&a[i]<=a[i*2+1](小根堆)
通俗来讲就是父节点一定大于等于其子节点或者小于等于其子节点。。。。
2.堆排序:一种树形选择排序方法。
特点:将a[1...n]看成是一棵完全二叉树的顺序存储结构。
时间复杂度:O(nlog₂n)
因为题目要求是从小到大,所以可以使用大根堆(若相反则可以使用小根堆)。
(1)数组有n个数,先将这个数组建树,也就是建大根堆,此时a[1]为所有元素的最大值。
(2)将a[1]和a[n]交换值,此时a[1~n-1]为无序,a[n]为有序数列。
(3)然后再将a[1]~a[n-1]进行调整堆,再将a[1]和a[n-1]进行交换值,此时a[n-1]和a[n]为有序,重复此操作就可将数组完整排完。
附上代码:
1 #include <stdio.h> 2 void swap(int a[],int x,int y)//交换数组值 3 { 4 int temp=a[x]; 5 a[x]=a[y]; 6 a[y]=temp; 7 } 8 void heapadjust(int a[],int i,int n)//调整整个树 9 { 10 int lchild=2*i;//左子节点 11 int rchild=2*i+1;//右子节点 12 int max=i;//先存下此时父节点 13 if(i<=n/2)//将父节点不是非叶节点排除 14 { 15 if(lchild<=n&&a[lchild]>a[max]) 16 max=lchild; 17 if(rchild<=n&&a[rchild]>a[max]) 18 max=rchild; 19 if(max!=i)//若最大值并不是父节点 20 { 21 swap(a,max,i); 22 heapadjust(a,max,n);//需要再调整以max为父节点的子树为堆 23 } 24 } 25 } 26 void heapbuild(int a[],int n)//建堆 27 { 28 int i; 29 for(i=n/2;i>=1;i--)//每次的调整需要从非叶节点,若有两个子节点则调整这三个数 30 { 31 heapadjust(a,i,n); 32 } 33 } 34 void heapsort(int a[],int n)//堆排序 35 { 36 int i; 37 heapbuild(a,n); 38 for(i=n;i>1;i--)//进行n-1趟完成堆排序,每一趟堆中元素个数减一 39 { 40 swap(a,1,i); 41 heapadjust(a,1,i-1); 42 } 43 } 44 int main(void) 45 { 46 int size,a[10],i; 47 printf("请输入排序个数,且个数小于10:"); 48 scanf("%d",&size); 49 printf("请输入%d个数字,以空格隔开:",size); 50 for(i=1;i<=size;i++) 51 scanf("%d",&a[i]); 52 heapsort(a,size); 53 printf("排序后:"); 54 for(i=1;i<=size;i++) 55 printf("%d ",a[i]); 56 printf("\n"); 57 return 0; 58 }
——————————————————————————-——————————————————————
Manba out ??
Not,Manba forever!