数据结构——第8章 排序

1 插入排序

**插入排序的基本思想:**前i-1个元素已经有序,将第i个数插入到该有序序列中。

**例:**打扑克牌时,手中的牌已经有序,每抓一张牌,就插入到合适的位置,直到抓完牌。

可以选择不同的方法在已排好序的记录中寻找插入位置: 根据查找方法的不同,这里分为直接插入排序(对应顺序查找)、折半插入排序(对应折半查找)和希尔排序。

1.1 直接插入排序

思路:

  1. r[1..n]为待排序的数组,此时,r[1]为有序序列
  2. 循环n-1次,每次使用顺序查找法,查找r[i] (i=2,...,n)在有序序列中的位置,然后插入。(这里的顺序查找,可以从前往后,也可以从后往前------设置监视哨,本文采用后者)
cpp 复制代码
void InsertSort(SqList &L){
	for(int i=2;i<=L.length;i++){
		if(L.r[i].score<L.r[i-1].score){
			L.r[0]=L.r[i];
			int j;
			for(j=i-1;L.r[0].score<L.r[j].score;j--){
				L.r[j+1]=L.r[j];
			}
			L.r[j+1]=L.r[0];
		}
	} 
}

时间复杂度:O(n^2)

空间复杂度:O(1)

算法特点:稳定算法、也适用于链式存储结构。

1.2 折半插入排序

思路:

  1. r[1..n]为待排序的数组,此时,r[1]为有序序列
  2. 循环n-1次,每次使用折半查找法,查找r[i] (i=2,...,n)在有序序列中的位置,然后插入。(如果能找到,high为答案)
cpp 复制代码
void BInsertSort(SqList &L){
	int low,high,mid; 
	for(int i=2;i<=L.length;i++){
		L.r[0]=L.r[i];
		low=1,high=i-1;
		while(low<=high){
			mid=(low+high)/2;
			if(L.r[0].score<L.r[mid].score) high=mid-1;
			else low=mid+1;
		}//如果能找到,答案为high
		int j;
		for(j=i-1;j>=high+1;j--){//将high之后的有序序列往后挪 
			L.r[j+1]=L.r[j]; 
		} 
		L.r[j+1]=L.r[0];//插入 
	} 
}

时间复杂度:O(n^2)

空间复杂度:O(1)

算法特点:稳定、不适用链式结构

1.3 希尔排序

思路:分组插入。对于每一趟,将相隔某个"增量"的记录分为一组,得到多组,每组都用插入排序使之有序。

  1. 第1趟取增量d1,所有间隔为d1的记录分在同一组,在各个组中进行直接插入排序
  2. 第2趟取增量d2(d2<d1),分组,插入排序。
  3. 依次类推,直到增量di为1,所有记录在同一组中进行插入排序。

2 交换排序

**交换排序的基本思想:**两两比较待排序记录的关键字,一旦发现两个记录不满足次序要求时则进行交换,直到整个序列全部满足要求为止。

2.1 冒泡排序

思路:大数下沉。

  1. 待排序数组为r[1..n]。**第1趟:首先将第1个记录和第2个记录的关键字进行比较,若为逆序,交换。然后比较第2个和第3个,......,第n-1个和第n个。**第1趟结束,最大的数下沉到最后的位置上。
  2. 然后进行第2趟,对前n-1个记录进行同样的操作。
  3. 重复,直至在某一趟排序过程中没有进行交换的操作,说明序列全部有序。(最差情况是进行n-1趟)
cpp 复制代码
void BubbleSort(SqList L){
	int m=L.length-1;//m表示趟数,一共需要Length-1趟
	int flag=1;//flag为1表示进行了交换 
	while(m>0&&flag==1){
		for(int i=1;i<=m;i++){
			flag=0;//没有进行交换
			if(L.r[i].score>L.r[i+1].score){
				flag=1;
				L.r[0]=L.r[i];
				L.r[i]=L.r[i+1];
				L.r[i+1]=L.r[0];
			} 
		}
		m--;

	}
}

时间复杂度:O(n^2)

空间复杂度:O(1)

算法特点:稳定、也适用于链式结构

2.2 快速排序

思路:任取一个记录作为轴,将关键字小于它的交换到前面,大于它的交换到后面。最后将轴放在交界处的位置

一趟快排Partition:

  1. 选第1个记录作为轴,暂存在r[0]的位置上。附设两个指针low和high。
  2. 从表的最右端向左搜索。当low<high时,while(r[high].key>=r[0].key),high--。搜索到小于r[0].key时,放到r[low]中(这里的r[low]相当于没有数据)。
  3. 然后从左往右。
  4. 重复2和3,直到low==high,完成一趟。
cpp 复制代码
int Partition(SqList &L,int low,int high){//对顺序表L中的子表r[low..high]进行一趟排序,返回轴的位置 
	L.r[0]=L.r[low];
	while(low<high){
		while(low<high&&L.r[high].score>=L.r[0].score) high--;
		L.r[low]=L.r[high];
		while(low<high&&L.r[low].score<=L.r[0].score) low++;
		L.r[high]=L.r[low];
	}  
	L.r[low]=L.r[0];
	return low;
}
void QSort(SqList &L,int low,int high){//对顺序表L的子序列L[low..high]进行快速排序 
	int loc;
	if(low<high){
		loc=Partition(L,low,high);		
		QSort(L,low,loc-1);
		QSort(L,loc+1,high);
	}
} 
void QuickSort(SqList &L){//对顺序表L进行快速排序 
	QSort(L,1,L.length); 
}

时间复杂度:O(nlogn)

空间复杂度: O(n) 因为快排是递归的,需要有一个栈来存放相应的数据。

算法特点:不稳定、不适用于链式结构。

3 选择排序

3.1 简单选择排序

3.2 树形选择排序

3.3 堆排序

4 归并排序

5 基数排序(桶排序)

6 外部排序

相关推荐
chenziang112 分钟前
leetcode hot 100 二叉搜索
数据结构·算法·leetcode
single5941 小时前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
呆头鹅AI工作室2 小时前
基于特征工程(pca分析)、小波去噪以及数据增强,同时采用基于注意力机制的BiLSTM、随机森林、ARIMA模型进行序列数据预测
人工智能·深度学习·神经网络·算法·随机森林·回归
一勺汤3 小时前
YOLO11改进-注意力-引入自调制特征聚合模块SMFA
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·目标跟踪
每天写点bug3 小时前
【golang】map遍历注意事项
开发语言·算法·golang
程序员JerrySUN3 小时前
BitBake 执行流程深度解析:从理论到实践
linux·开发语言·嵌入式硬件·算法·架构
王老师青少年编程4 小时前
gesp(二级)(16)洛谷:B4037:[GESP202409 二级] 小杨的 N 字矩阵
数据结构·c++·算法·gesp·csp·信奥赛
robin_suli5 小时前
动态规划子序列问题系列一>等差序列划分II
算法·动态规划
cxylay5 小时前
自适应滤波算法分类及详细介绍
算法·分类·自适应滤波算法·自适应滤波·主动噪声控制·anc
茶猫_5 小时前
力扣面试题 - 40 迷路的机器人 C语言解法
c语言·数据结构·算法·leetcode·机器人·深度优先