数据结构——选择排序

简单选择排序

算法原理
  1. iii趟,从所有元素中选择关键字最小的元素与A[i]A[i]A[i]交换
  2. 每趟排序可以确定一个元素的最终位置,通过n−1n-1n1趟排序后整个序列有序
代码实现
void SelectSort(int A[], int n){
	int i, j, min, k;
	for(i=1; i<n; i++){
		min = i;
		for(j=i+1; j<=n; j++)
			if(A[j] < A[min])
				min = j;
		if(min != i){
			k = A[i];
			A[i] = A[min];
			A[min] = k;
		}
	}
}
举例

在这里插入图片描述

性能分析
  • 空间效率:只使用常数个辅助单元,空间复杂度为O(1)O(1)O(1)
  • 时间效率:最好情况下,不需要交换元素;最坏情况下,交换3(n−1)3(n-1)3(n1)次。比较的次数是固定的,为n(n−1)2\frac{n(n-1)}{2}2n(n1)次,时间复杂度为O(n2)O(n^2)O(n2)
  • 稳定性:不稳定

堆排序

算法原理
  • 堆的定义:n个关键字序列A[1…n]称为堆,当且仅当序列满足
    A[i]>=A[2i]且A[i]>=A[2i+1]或(1)A[i]>=A[2i]且A[i]>=A[2i+1]或\tag{1}A[i]>=A[2i]A[i]>=A[2i+1](1)
    A[i]<=A[2i]且A[i]<=A[2i+1](1<=i<=⌊n/2⌋)(2)A[i]<=A[2i]且A[i]<=A[2i+1](1<=i<=\lfloor{n/2\rfloor})\tag{2}A[i]<=A[2i]A[i]<=A[2i+1](1<=i<=n/2)(2)
  • 可以将堆视为一棵完全二叉树,满足(1)(1)(1)的堆称为大根堆(大顶堆),满足(2)(2)(2)的称为小根堆(小顶堆)
  • 算法步骤(以大顶堆为例)
    1. 将n个元素的序列建成初始堆,输出堆顶元素
    2. 将堆底元素送入堆顶,从根开始向下调整,使其保持堆的性质,再输出堆顶元素
    3. 重复2,直到堆中仅剩下一个元素为止
  • 堆的调整
    1. 对第⌊n/2⌋\lfloor n/2 \rfloorn/2个结点为根的子树进行筛选(若根结点的关键字小于左右孩子中关键字较大者,则交换),使子树变成堆
    2. 向前依次对各个结点(⌊n/2⌋−1∼1\lfloor n/2\rfloor-1\sim 1n/211)为根的子树进行筛选,由于交换会破坏下一级的堆,于是继续筛选,构造下一级的堆,直到以该结点为根的子树变成堆为止。
    3. 重复第2步建堆,直到根结点
代码实现
void HeapAdjust(int A[], int k, int len){
	int i;
	A[0] = A[k];
	for(i=2*k; i<=len; i*=2){
		if(i<len && A[i]<A[i+1])
			i++;					// 孩子结点中关键字较大结点的下标
		if(A[0] > A[i])				// 若父结点的关键字大,不需要调整
			break;
		else{						// 父结点与较大孩子结点交换
			A[k] = A[i];
			k = i;					// 修改k值,向下调整堆
		}
	}
	A[k] = A[0];					// 被调整结点放入最终位置
}

void HeapSort(int A[], int len){
	int k;
	for(int i=len/2; i>0; i--)		// 初始化堆
		HeapAdjust(A, i, len);
	for(int i=len; i>1; i--){		// 交换堆顶元素到最终结果位置,并调整堆
		k = A[i];
		A[i] = A[1];
		A[1] = k;
		HeapAdjust(A, 1, i-1);
	}
}
举例

在这里插入图片描述

性能分析
  • 空间效率:仅使用了常数个辅助单元,空间复杂度为O(1)O(1)O(1)
  • 时间效率:建堆的时间为O(n)O(n)O(n),然后进行n−1n-1n1次调整,每次调整的时间复杂度为O(h)O(h)O(h),故在最好、最坏、平均情况下,堆排序的时间复杂度为O(nlog⁡2n)O(n\log_2n)O(nlog2n)
  • 稳定性:不稳定
数据结构中的排序算法是指一种将一串数据按照特定顺序(通常是升序或降序)排列的方法。常见的排序算法有多种,每种都有其特点和适用场景: 1. **冒泡排序**(Bubble Sort):简单直观,通过不断交换相邻元素使得较大值逐渐“浮”到数组顶部。效率较低,适用于小规模数据。 2. **选择排序**(Selection Sort):每次从未排序部分找出最小(大)元素,放到已排序部分的末尾。不稳定,对大规模数据效率不高。 3. **插入排序**(Insertion Sort):类似于打扑克牌,将每个元素逐个插入到已排序的部分的适当位置。效率随着数据有序程度提高而提升。 4. **快速排序**(Quick Sort):采用分治策略,选取一个基准元素,将序列分为两部分,一部分小于基准,另一部分大于基准,然后递归地对这两部分进行排序。平均性能好,是一种常用的高效排序法。 5. **归并排序**(Merge Sort):同样基于分治,将数组分成两个子数组,分别排序后再合并。稳定,但需要额外的空间存储。 6. **堆排序**(Heap Sort):利用堆这种数据结构特性,构建最大堆或最小堆进行排序。原地操作,效率较高。 7. **计数排序**(Counting Sort):针对非负整数,统计每个元素出现次数,再根据次数重构有序序列。时间复杂度低至线性,但只能处理整数范围有限的情况。 8. **基数排序**(Radix Sort):按位数从最低位到最高位进行排序,适合数字类型的整数排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值