选择排序之堆排序

#include<stdio.h>
#include<stdlib.h>
void swap(int* data, int i, int j){
	int temp;
	temp = data[i];
	data[i] = data[j];
	data[j] = temp;
}
//优美的递归实现堆调整 
void adjustBigTopHeap(int* data, int root, int n){
		int leftChildIndex = root*2;
		int rightChildIndex = leftChildIndex + 1;
		//max用来指向(父节点、左孩子节点和右孩子节点三者中)值最大的节点的下标,初始值为父节点的下标 
		int max = root;
		/*仅对以非叶子节点为根的树进行调整,非叶子节点的数组下标,取值范围为[1, n/2]*/ 
		if(1 <= root <= n/2){  
		
		//左孩子若存在,且其值大于父节点的值	
		if(leftChildIndex <= n && data[leftChildIndex] > data[max]){
			max = leftChildIndex;
			 
			//右孩子若存在,且其值大于左孩子和父节点 (把这个if嵌套在里面是因为堆也是一棵二叉树,只有左孩子存在,右孩子才有可能存在)
			if(rightChildIndex <= n && data[rightChildIndex] > data[max])
				max = rightChildIndex;
		} 
		//max != root, 意味着左孩子或右孩子大于父节点的值 ,即根为root的二叉树的大顶堆性质被破坏,需重新调整 
		if(max != root){
			swap(data, root, max);
			//在其值发生交换后,以左孩子或右孩子为根的二叉树,其大顶堆性质可能被破坏,需对其重新调整
			adjustBigTopHeap(data, max, n);
		} 	
		/*如果max == root,意味着根为root的二叉树仍满足大顶堆性质,亦无需再向下调整(其子树因为没有发生值交换,故大顶堆性质没有被破坏)*/ 
	} 
}

void buildBigTopHeap(int* data, int n){
	for(int i = n/2; i >=1; i--)
		adjustBigTopHeap(data, i, n);	
}

void bigTopHeapSort(int* data, int n){
	//构造大顶堆 
	buildBigTopHeap(data, n);
	//进行一系列取顶和调整大顶堆操作,直到堆只有一个元素(为方便计算,根节点的下标从1开始) 
	for(int i = n; i > 1; i--){
		//取顶,并将结果保存在当前趟的最后一位(对应i位) 
		swap(data, 1, i);
		//root是编号为1的二叉树的大顶堆性质被破坏,需重新调整,又因为第i位用来存当前趟已确定的最值,故只需调整下标为1~i - 1的数组元素 
		adjustBigTopHeap(data, 1, i - 1);		
	}
}
int main(void){
	int* testData;
	int n;
	printf("请输入数组的大小(n <= 0 时结束):");
	while(scanf("%d",&n) == 1 && n > 0){
		//因为从数组从下标1开始存数,所有应生成n + 1个int大小的空间,才能存n个数。 
		testData = (int*)malloc((n + 1)*sizeof(int));
		printf("请输入%d个随机的无序整数:",n);
		for(int i = 1; i <= n; i++)
			scanf("%d", &testData[i]);
		bigTopHeapSort(testData, n);
		printf("排序后的结果为:");
		for(int i = 1; i <= n; i++)
			printf("%d ", testData[i]);
		printf("\n请输入数组的大小(n <= 0 时结束):"); 
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值