八种排序算法

排序算法:

八种排序算法总结:

在这里插入图片描述

冒泡排序:

描述:

  1. 比较相邻的元素,如果第一个比第二个大就交换

  2. 对每一对相邻的元素进行同样的操作,这步做完之后最后的元素是最大的数

  3. 每次对越来越少的元素执行相同的步骤

    //冒泡排序  时间复杂度(平均):O(n^2)  空间复杂度:O(1)  稳定性:稳定
    void BabbleSort(int n, int arr[])
    {
    	//安全检查
    	if (arr == nullptr || n <= 0)
    	{
    		return;
    	}
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = 0; j < n - i - 1; j++)
    		{
    			if (arr[j] > arr[j + 1])
    			{
    				Swap(j, j + 1, arr);
    			}
    		}
    	}
    }
    
快速排序:

描述:

  1. 从列表中选择一个作为基准 base
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
//快排  时间复杂度(平均):O(nlog 2 n)  空间复杂度:O(nlog 2 n)  稳定性:不稳定
void QuickSort(int left, int right, int arr[])
{
	//安全检查
	if (left > right || left < 0 || right < 0) return;
	int i, j, temp, base;
	i = left;
	j = right;
	base = arr[left];
	while (i < j)
	{
		while (i < j && arr[j] >= base) j--;
		while (i < j && arr[i] <= base) i++;
		if (i < j)
		{
			Swap(i, j, arr);
		}
	}
	//基数归位
	arr[left] = arr[i];
	arr[i] = base;
	QuickSort(left, i - 1, arr);
	QuickSort(i + 1, right, arr);
}
直接选择排序

描述:

  1. 首先在未排序的序列中记录第一位为最小值的位置
  2. 再从剩余的元素中寻找比最小值大的并交换位置
//直接选择排序  时间复杂度(平均):O(n^2)  空间复杂度:O(1)  稳定性:不稳定
void SelectSort(int n, int arr[])
{
	//安全检查
	if (n <= 0) return;
	int min;
	for (int i = 0; i < n - 1; i++)
	{
		//记录最小值的位置
		min = i;
		for (int j = i + 1; j < n; j++)
		{
			if (arr[min] > arr[j])
			{
				min = j;
			}
		}
		if (i != min)
		{
			Swap(i, min, arr);
		}
	}
}
直接插入排序:

描述:

  1. 将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
  2. 从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
//直接插入排序   时间复杂度(平均):O(n^2)  空间复杂度:O(1)  稳定性:稳定
void InsertSort(int n, int arr[])
{
	//安全检查
	if (n <= 0) return;
	for (int i = 1; i < n; i++)
	{
		int temp = arr[i];
		int j = i - 1;
		while (j >= 0 && arr[j] > temp)
		{
			arr[j + 1] = arr[j];
			j--;
		}
		arr[j + 1] = temp;
	}
}
希尔排序:

描述:

  1. 设置增量序列
  2. 控制分组
  3. 直接插入排序
  4. 增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
//希尔排序 时间复杂度(平均):O(n^1.3)  空间复杂度:O(1)  稳定性:不稳定
void ShellSort(int n, int arr[])
{

	//控制增量 
	for (int gap = n / 2; gap >= 1; gap = gap / 2)
	{
		//控制分组
		for (int k = 0; k < gap; k++)
		{
			//直接插入排序
			for (int i = k + gap; i < n; i += gap)
			{
				//默认第一个元素有序,每次从最后一个有序增量单位开始
				int tamp = arr[i];
				//游标指向有序序列最后一个元素
				int j = i - gap;
				while (j >= 0 && tamp < arr[j])
				{
					//移动增量个单位
					arr[j + gap] = arr[j];
					j -= gap;
				}
				arr[j + gap] = tamp;
			}
		}
	}
}
堆排序:

描述:

  1. 创建一个堆
  2. 把堆首(最大值)和堆尾交换
  3. 递归调整其他不满足堆性质的部分
//堆排序 时间复杂度(平均):O(nlog 2 n)  空间复杂度:O(1)  稳定性:不稳定
void Adjust(int arr[], int len, int index)
{
	int left = 2 * index + 1;
	int right = 2 * index + 2;
	int maxId = index;
	if (left<len && arr[left]>arr[maxId]) maxId = left;
	if (right<len && arr[right]>arr[maxId]) maxId = right;// 到此maxIdx是3个数中最大数的下标
	if (maxId != index)// 如果maxIdx的值有更新
	{
		Swap(maxId, index, arr);
		Adjust(arr, len, maxId);// 递归调整其他不满足堆性质的部分
	}
}

void HeadSort(int n, int arr[])
{
	for (int i = n / 2; i >= 0; i--)   // 对每一个非叶结点进行堆调整(从最后一个非叶结点开始)
		Adjust(arr, n, i);
	for (int i = n - 1; i >= 1; i--)
	{
		Swap(i, 0, arr); // 将当前最大的放置到数组末尾
		Adjust(arr, i, 0); // 将未完成排序的部分继续进行堆排序
	}

}
归并排序:

描述:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;result
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置; start end
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
  4. 重复步骤 3 直到某一指针达到序列尾;
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。
//归并排序  时间复杂度(平均):O(nlog 2 n)  空间复杂度:O(1)  稳定性:稳定

void Merge(int* data, int start, int end, int* result)
{
	int left_length = (end - start + 1) / 2 + 1;//左部分区间元素的个数
	int left_index = start;
	int right_index = start + left_length;
	int result_index = start;
	while (left_index < start + left_length && right_index < end + 1)
	{
		//对分别已经拍好的左区间和右区间进行合并
		if (data[left_index] <= data[right_index])
			result[result_index++] = data[left_index++];
		else
			result[result_index++] = data[right_index++];
	}
	while (left_index < start + left_length)
		result[result_index++] = data[left_index++];
	while (right_index < end + 1)
		result[result_index++] = data[right_index++];

}




void MegeSort(int* data, int start, int end, int* result)
{
	//如果区间中只有两个元素 对这两个元素进行排序
	if (end - start == 1)
	{
		if (data[start] > data[end])
		{
			Swap(start, end, data);
		}
		return;
	}
	if (end - start == 0)
		return;//如果只有一个元素 则不用排序
	else
	{
		//继续划分子区间,分别对左右子区间进行排序
		MegeSort(data, start, (end - start + 1) / 2 + start, result);
		MegeSort(data, (end - start + 1) / 2 + start + 1, end, result);
		//开始归并已经排好序的start到end之间的数据
		Merge(data, start, end, result);
		//把排序后的区间数据复制到原始数据中去
		for (int i = start; i <= end; ++i)
			data[i] = result[i];
	}

}
基数排序:

描述:

基数排序(以整形为例),将整形10进制按每位拆分,然后从低位到高位依次比较各个位。每次比较完进行排序,直到整个数组有序

主要分为两个过程:

(1)分配,先从个位开始,根据位值(0-9)分别放到0~9号桶中(比如53,个位为3,则放入3号桶中)

(2)收集,再将放置在0~9号桶中的数据按顺序放到数组中

重复(1)(2)过程,从个位到最高位,直到排好序为止(比如32位无符号整形最大数4294967296,最高位10位)

img

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值