数据结构--插入、希尔、选择、冒泡排序

排序的动图演示链接

1.插入排序

(1)算法描述
① 从第一个元素开始,该元素认为已经被排好序;
② 取出下一个元素,在已经排好序的元素序列中从后向前比较;
③ 如果已排好序的元素大于新元素,将该元素移到下一位置;
④ 重复③,直至找到已排好序的元素小于或等于新元素,将新元素插入该位置;
⑤ 重复②③④。

(2)代码实现

//插入排序  时间复杂度:O(n^2)
void insertSort(int* arr, int n)
{
	//假设第一个数据已经有序,插入的数据:[1,n]
	for (int i = 1; i < n; i++)
	{
		//从有序数据的最后一个位置向前遍历
		int end = i - 1;
		int tmp = arr[i];
		//while (end >= 0 && arr[end] >= tmp)  不稳定
		while (end >= 0 && arr[end] > tmp)  //稳定
		{
			//大的数据向后移动
			arr[end + 1] = arr[end];
			end--;
		}
		arr[end + 1] = tmp;
	}
}
//输出函数
void printArr(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

在这里插入图片描述

2.希尔排序

(1)算法描述
① 选择一个递减的增量序列,例如5、2、1;
② 按照增量序列个数k,对序列进行k趟排序;
③ 每趟排序,根据对应的增量,将待排序的序列分割成若干长度为m的子序列,对子序列进行插入排序,最后一趟排序,间隔必须是1,保证所有的数据在同一个序列中。

(2)代码实现

//希尔排序  时间复杂度O(n^1.3)   不稳定
void shellSort(int* arr, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		//最后一趟排序,间隔必须是1,保证所有数据在同一组
		//一趟希尔排序   
		for (int i = gap; i < n; i++)
		{
			//同组数据,最后一个有序的数据的位置
			int end = i - gap;
			//待插入的数据
			int data = arr[i];
			while (end >= 0 && arr[end] > data)
			{
				arr[end + gap] = arr[end];
				end -= gap;
			}
			arr[end + gap] = data;
		}
	}
}

在这里插入图片描述

3.选择排序

(1)算法描述
① 初始状态:未排序的区间[1,n];
② 第i趟排序开始时,当前有序区间和无序区间分别为[i,i-1]、[i,n],从无序区间找到最小值,然后将其与无序区间的第一个值交换,更新有序和无序区间;
③ 重复②,直至n-1趟结束,数据有序。

(2)代码实现

//选择排序  时间复杂度:O(n^2)   稳定   
void selectSort1(int* arr, int n)
{
	//从未排序的序列中找出最值,存放在未排序的起始位置
	//未排序区间[start,end];
	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])  不稳定
			if (arr[i] < arr[minidx])
				minidx = i;
		}
		//把最小值存到最开始的位置
		swap(arr, start, minidx);
		//剩余未排序的位置区间[start + 1, end];
		++start;
	}
}
//遍历的次数减少一半的选择排序
void selectSort2(int* arr, int n)
{
	int start = 0;
	int end = n - 1;
	//每次未排序的区间找到一个最大值和最小值
	//最小值放在头部,最大值放在尾部
	while (start < end)
	{
		int minidx = start;
		int maxidx = start;
		for (int j = start + 1; j <= end; j++)
		{
			if (arr[j] < arr[minidx])
				minidx = j;
			if (arr[j] > arr[maxidx])
				maxidx = j;
		}
		//把最小值存放在最开始的位置
		swap(arr, start, minidx);
		//判断最大值的位置是否在起始位置
		if (maxidx == start)
			maxidx = minidx;
		//最大值存放在末尾
		swap(arr, end, maxidx);
		++start;
		--end;
	}
}

在这里插入图片描述

4. 冒泡排序

(1)算法描述
① 比较相邻的元素,如果第一个元素大于第二个,交换;
② 对每一对相邻元素进行①(第一次遍历完成后,最后一个数即为最大数);
③ 重复执行②,直至排序完成。

(2)代码实现

//冒泡排序  时间复杂度O(n^2)  数据有序:O(n)  稳定
void bubbleSort(int* arr, int n)
{
	//相邻元素进行比较
	//第一次遍历的范围:0~未排序数据的最后一个位置
	//flag:标记一轮冒泡排序中是否发生了交换
	int flag = 0;
	int end = n;
	while (end > 1)
	{
		//一轮冒泡排序
		for (int i = 1; i < end; ++i)
		{
			if (arr[i - 1] > arr[i]) {
				//大的数向后移动
				swap(arr, i - 1, i);
				flag = 1;
			}
		}
		//如果没有发生交换,说明剩余元素全部有序
		if (!flag)
			break;
		--end;
	}
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值