数据结构--直接选择排序和堆排序

1 选择排序

每一次从待排序的数据元素中选出最小(最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

2 直接选择排序

2.1 基本思想

  • 在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素
  • 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
  • 在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

2.2 算法示意图

在这里插入图片描述

2.3 程序代码

#include<stdio.h>
#include<stdlib.h>

/*选择排序:每一次从未排序的数据中找到一个最小的,
把最小的放到未排序的数据的头部,不断重复
*/
void swap(int* arr, int pos1, int pos2) {
	int tmp = arr[pos1];
	arr[pos1] = arr[pos2];
	arr[pos2] = tmp;
}
void selectSort(int* arr, int n) {
	//从未排序的序列中找到最值,存放到未排序的起始位置
	//未排序区间
	int start = 0; 
	int end = n - 1;
	while (start < end) {
		int minIdx = start;
		for (int i = start + 1; i <= end; i++) {
			if (arr[i] < arr[minIdx])
				minIdx = i;
		}
		//把最小值存放在最开始的位置
		swap(arr, start, minIdx);
		//剩余的未排序区间[start + 1 , end]
		start++;
	}
}

2.4 验证代码

void testSelectSort() {
	int arr[] = { 9 ,1,2,5,7,4,8,6,3,5 };
	int n = sizeof(arr) / sizeof(arr[0]);
	selectSort(arr, n);
	for (int i = 0; i < n; i++) {
		printf("%d ", arr[i]);
	}
}
int main(){
	testSelectSort();
	return 0;
}

运行结果如下:
在这里插入图片描述

2.5 直接选择排序特性

  • 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  • 时间复杂度: O ( N 2 ) O(N^2) O(N2)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:不稳定

2.6 选择排序的优化

每次选最大值和最小值,同时进行比较

#include<stdio.h>
#include<stdlib.h>

void selectSort2(int* arr, int n) {
	int start = 0;
	int end = n - 1;
	//每次从未排序的区间中找到一个最大值,一个最小值
	//min放在头部,max放在尾部
	while (start < end) {
		int maxIdx = start;
		int minIdx = start;
		for (int i = start + 1; i <= end; i++) {
			if (arr[i] > arr[maxIdx])
				maxIdx = i;
			if (arr[i] < arr[minIdx])
				minIdx = i;
		}
		swap(arr, start, minIdx);
		//判断最大值是否为start
		if (maxIdx == start)
			maxIdx = minIdx;
		swap(arr, end, maxIdx);
		start++;
		end--;
	}
}

void testSelectSort2() {
	int arr[] = { 9 ,1,2,5,7,4,8,6,3,5 };
	int n = sizeof(arr) / sizeof(arr[0]);
	selectSort2(arr, n);
	for (int i = 0; i < n; i++) {
		printf("%d ", arr[i]);
	}
}
int main(){
	testSelectSort2();
	return 0;
}

3 堆排序

3.1 基本思想

堆排序是指利用堆这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。
需要注意的是排升序要建大堆,排降序建小堆。

3.2 算法示意图

在这里插入图片描述
在这里插入图片描述

3.3 程序代码

#include<stdio.h>
#include<stdlib.h>

typedef int HPDataType;
/*实现数组中两个位置值的交换*/
void Swap(HPDataType* arr, int idx1, int idx2) {
	HPDataType tmp = arr[idx1];
	arr[idx1] = arr[idx2];
	arr[idx2] = tmp;
}
/*实现大根堆
向下调整算法,传入存储堆的数组及长度,需要执行向下调整的节点序号
*/
void bigShifDown(HPDataType* arr, int n, int cur) {
	//找到孩子的位置
	int child = cur * 2 + 1;
	while (child < n) {
		//存在孩子,比较两个孩子,找到值最小的一个
		if (child + 1 < n && arr[child + 1] > arr[child])
			child = child + 1;
		//和当前数据进行比较
		if (arr[cur] < arr[child]) {
			//交换当前节点与值最小的孩子
			Swap(arr, child, cur);
			//更新位置,继续调整
			cur = child;
			child = 2 * cur + 1;
		}
		else
			break;
	}
}

//堆排序
void HeapSort(int* arr, int n) {
	//建堆
	for (int i = (n - 2) / 2; i >= 0; i--) {
		bigShifDown(arr, n, i);
	}

	//堆排序
	int end = n - 1;
	while (end > 0) {
		//堆顶元素的删除:交换+向下调整
		Swap(arr, 0, end);
		bigShifDown(arr, end, 0);
		end--;
	}
}

3.4 验证代码

void testHeapSort() {
	int arr[] = { 9 ,1,2,5,7,4,8,6,3,5 };
	int n = sizeof(arr) / sizeof(arr[0]);
	HeapSort(arr, n);
	for (int i = 0; i < n; i++) {
		printf("%d ", arr[i]);
	}
}
int main() {
	testHeapSort();
	return 0;
}

运行结果如下:
在这里插入图片描述

3.5 堆排序特性

  • 堆排序使用堆来选数,效率就高了很多。
  • 时间复杂度: O ( N l o g ( N ) ) O(Nlog(N)) O(Nlog(N))
  • 空间复杂度: O ( 1 ) O(1) O(1)
  • 稳定性:不稳定
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值