八大排序源码(含优化)

news2024/11/25 10:55:26

文章目录

  • 1、直接插入排序
  • 2、希尔排序
  • 3、选择排序
  • 4、冒泡排序
  • 5、堆排序
  • 6、快速排序
    • 快速排序递归实现
      • 霍尔法
      • 挖坑法
      • 前后指针法
      • 快速排序小区间优化
    • 快速排序非递归实现
  • 7、归并排序
    • 归并排序递归实现
    • 归并排序非递归
  • 8、计数排序

大家好,我是纪宁,这篇文章是关于八大排序的源代码,具体实现过程会在后续文章中介绍。

1、直接插入排序

时间复杂度O(N^2),原数据越有序,效率越高。
当原数据有序时,则时间复杂度为O(N)。原数据倒序时,时间复杂度为O(N^2)
在这里插入图片描述

void InsertSort(int* a, int n)//直接插入排序
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end+1];
		while (end >= 0)
		{
			if (a[end] >tmp)
			{
				a[end + 1] = a[end];
			}
			else
			{
				break;
			}
			end--;
		}
		a[end + 1] = tmp;
	}
}

2、希尔排序

时间复杂度:O(N*logN) 空间复杂度:O(1)
希尔排序是插入排序的优化,整体思路是先预排序,使原数据更接近有序,等到gap==1时,就变成了直接插入排序。

void ShellSort(int* arr, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;//gap也可以 /=2;奇特数字必须保证gap最后的值为1
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = arr[end + gap];
			while (end >= 0)
			{
				if (tmp < arr[end])
				{
					arr[end + gap] = arr[end];
				}
				else
				{
					break;
				}
				end -= gap;
			}
			arr[end + gap] = tmp;
		}
	}
}

3、选择排序

时间复杂度:O(N^2) 空间复杂度:O(1)
每次选择一个最大或者最小的数,使其出现在正确的位置。
在这里插入图片描述

void SelectSort(int* a, int n)
{
	for (int j = 0; j < n; j++)
	{
		int mini = j;
		int maxi= n - j-1;
		for (int i = j; i < n-j; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		Swap(&a[mini], &a[j]);
		if (maxi == j)
		{
			maxi = mini;//最大值如果在 j 这个位置的话,结果这个位置被换成了min 的值
		}
		Swap(&a[maxi], &a[n-1-j]);
	}
}

4、冒泡排序

时间复杂度:O(N^2) 空间复杂度:O(1)
思路最简单的排序,所有程序员的白月光!
在这里插入图片描述

void BubbleSort(int* a, int n)//冒泡排序
{
	for (int i = 0; i < n; i++)
	{
		int ret = 0;//如果一趟后ret还等于0,说明数据已经有序
		for (int j = 0; j < n - i - 1; j++)
		{
			if (a[j] > a[j + 1])
			{
				Swap(&a[j], &a[j + 1]);
				ret = 1;
			}
		}
		if (ret == 0)
			break;
	}
}

5、堆排序

时间复杂度:O(N*logN) 空间复杂度:O(1)
建堆的时候可以采用向上调整和向下调整建堆,而排序的时候只能使用向下调整算法。
排升序建大堆,降序建小堆。

void Adjustup(int* a, int child)//向上调整
{
	int parent = (child - 1) / 2;
	while (parent >= 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void Adjustdown(int* a, int parent, int n)//向下调整
{
	int child = 2 * parent + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* arr, int sz)
{
	//第一步,建堆
	向上调整建堆
	
	//for (int i = 1; i < sz; i++)
	//{
	//	Adjustup(arr, i); 
	//}
	//向下调整建堆

	for (int i = (sz - 1) / 2; i >= 0; i--)
	{
		Adjustdown(arr, i, sz - 1);
	}
	int end = sz - 1;
	while (end > 0)
	{
		Swap(&arr[0], &arr[end]);
		Adjustdown(arr, 0, end);
		end--;
	}
}

6、快速排序

时间复杂度:O(N*logN) 空间复杂度:O(1)

快速排序递归实现

霍尔法

在这里插入图片描述

int QuickSortPart1(int*a,int left,int right)//霍尔版本
{
	int* Maxi = (&a[left], &a[right], &(a[(left + right) / 2]));//三数取中
	Swap(&a[left], Maxi);//换到最左边
	int key = a[left];
	int keyi = left;
	while (left<right)
	{
		while (left<right && a[right]>=key)
		{
			right--;
		}
		while (left < right && a[left] <= key)
		{
			left++;
		}
		Swap(&a[left], &a[right]);
	}
	Swap(&a[keyi], &a[left]);
	return left;
}
void QuickSort(int*arr, int begin, int end)
{
	if (begin >= end)//等于是只有一个数需要排,大于是没有数需要排
	{
		return;
	}
	int keyi = QuickSortPart1(arr, begin, end);
	/*int keyi = QuickSortPart2(arr, begin, end);
	int keyi = QuickSortPart3(arr, begin, end);*/
	QuickSort(arr, begin, keyi - 1);
	QuickSort(arr, keyi + 1, end);
}

挖坑法

在这里插入图片描述

int QuickSortPart2(int* arr, int left, int right)//挖坑法
{
	int* Maxi = (&arr[left], &arr[right], &(arr[(left + right) / 2]));
	Swap(&arr[left], Maxi);
	int holei = left;
	int hole = arr[left];
	while (left < right)
	{
		while (left < right && arr[right] >= hole)
		{
			right--;
		}
		arr[holei] = arr[right];
		holei = right;
		while (left < right && arr[left] <= hole)
		{
			left++;
		}
		arr[holei] = arr[left];
		holei = left;
	}
	arr[holei] = hole;
	return left;
}
void QuickSort(int*arr, int begin, int end)
{
	if (begin >= end)//等于是只有一个数需要排,大于是没有数需要排
	{
		return;
	}
	/*int keyi = QuickSortPart1(arr, begin, end);*/
	int keyi = QuickSortPart2(arr, begin, end);
	/*int keyi = QuickSortPart3(arr, begin, end);*/
	QuickSort(arr, begin, keyi - 1);
	QuickSort(arr, keyi + 1, end);
}

前后指针法

在这里插入图片描述

int QuickSortPart3(int* a, int left, int right)//快排快慢指针
{
	int* Maxi = (&a[left], &a[right], &(a[(left + right) / 2]));
	Swap(&a[left], Maxi);
	int keyi = left;
	int prev = left;
	int cur = left+1;
	while (cur <= right)
	{
		if (a[cur] < a[keyi]&& ++prev!= cur)
		{
			Swap(&a[prev], &a[cur]);
		}
		cur++;
	}
	Swap(&a[prev],&a[keyi]);
	return prev;
}

void QuickSort(int*arr, int begin, int end)
{
	if (begin >= end)//等于是只有一个数需要排,大于是没有数需要排
	{
		return;
	}
	//*int keyi = QuickSortPart1(arr, begin, end);*/
	//int keyi = QuickSortPart2(arr, begin, end);
	int keyi = QuickSortPart3(arr, begin, end);
	QuickSort(arr, begin, keyi - 1);
	QuickSort(arr, keyi + 1, end);
}

快速排序小区间优化

void QuickSort1(int* a, int begin, int end)
{
	if (begin >= end)
		return;

	// 小区间优化,小区间不再递归分割排序,降低递归次数
	if ((end - begin + 1) > 10)
	{
		int keyi = PartSort3(a, begin, end);

		// [begin, keyi-1] keyi [keyi+1, end]
		QuickSort1(a, begin, keyi - 1);
		QuickSort1(a, keyi + 1, end);
	}
	else
	{
		InsertSort(a + begin, end - begin + 1);//直接插入排序
	}
}

快速排序非递归实现

快排非递归要用栈来实现

void QuickSortNorn(int* a, int begin, int end)
{
	ST st;//创建数组栈
	STInit(&st);//初始化栈
	STPush(&st, end);//入栈
	STPush(&st, begin);//入栈
	while (!STEmpty(&st))//判空
	{
		int left = STTop(&st);//取栈顶数据
		STPop(&st);//出栈
		int right = STTop(&st);
		STPop(&st);

		int keyi = QuickSortPart1(a, left,right);
		if (keyi + 1 < right)
		{
			STPush(&st, right);
			STPush(&st, keyi + 1);
		}
		if (keyi - 1 > left)
		{
			STPush(&st, keyi - 1);
			STPush(&st, left);
		}
	}
	STDestroy(&st);//销毁栈
}

7、归并排序

时间复杂度:O(N*logN) 空间复杂度:O(N)

归并排序递归实现

在这里插入图片描述

void _MergeSortPart(int* a, int* tmp, int begin, int end)
{
	if (begin >= end)
		return;
	int midi = (begin + end) / 2;
	_MergeSortPart(a, tmp, begin, midi);
	_MergeSortPart(a, tmp, midi + 1, end);
	int begin1 = begin, end1 = midi;
	int begin2 = midi + 1, end2 = end;
	int index = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[index++] = a[begin1++];
		}
		else
		{
			tmp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}
	memcpy(a+begin, tmp+begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	_MergeSortPart(a, tmp, 0, n - 1);
	free(tmp);
	tmp = NULL;
}

归并排序非递归

void _MergeSortNonr(int* a, int* tmp, int begin, int end)
{
	int gap = 1;
	while (gap <= end)
	{
		for (int i = 0; i <= end; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			int index = i;
			if (begin2 > end)
			{
				break;
			}
			if (end2 > end)
			{
				end2 = end;//对范围进行修正
			}
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[index++] = a[begin1++];
				}
				else
				{
					tmp[index++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[index++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[index++] = a[begin2++];
			}
			memcpy(a + i, tmp + i, sizeof(int) * (end2-i+1));//拷贝回原数组
		}
	gap *= 2;
	}
	 
}
void MergeSortNonr(int* a, int n)//归并排序非递归
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	_MergeSortNonr(a, tmp, 0, n - 1);
	free(tmp);
	tmp = NULL;
}

8、计数排序

时间复杂度:O(MAX(N,range)) 空间复杂度:O(range)

void CountSort(int* a, int n)//计数排序
{
	//先找最大值和最小值
	int maxi = 0, mini = 0;
	for (int i = 1; i < n; i++)
	{
		if (a[i] > a[maxi])
		{
			maxi = i;
		}
		if (a[i] < a[mini])
		{
			mini = i;
		}
	}
	int max = a[maxi], min = a[mini];
	int range = a[maxi] - a[mini]+1;
	int* count = (int*)malloc(sizeof(int) * range);
	memset(count, 0, sizeof(int) * range);
	for (int j = 0; j < n; j++)
	{
		count[a[j] - min]++;
	}
	int i = 0;
	for (int j = 0; j < n; j++)
	{
		while (count[j]--)
		{ 
			a[i++] = j + min;
		}
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1053757.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

36.骑士周游算法及其基于贪心算法的优化

概述 骑士周游算法&#xff0c;叫做“马踏棋盘算法”或许更加直观。在国际象棋8x8的棋盘中&#xff0c;马也是走“日字”进行移动&#xff0c;相应的产生了一个问题&#xff1a;“如果要求马 在每个方格只能进入一次&#xff0c;走遍全部的64个方格需要如何行进&#xff1f;”…

【STM32基础 CubeMX】按键的检测

文章目录 前言一、按键原理图分析二、cubeMX配置key GPIO三、代码分析3.1 cubemx生成的代码3.2 1个库函数 四、按键点灯示例代码总结 前言 在嵌入式系统开发中&#xff0c;按键检测是一个基础而重要的任务&#xff0c;特别是在使用STM32系列微控制器的项目中。按键通常被用于与…

C++ - 开放地址法的哈希介绍 - 哈希表的仿函数例子

前言 哈希其实是一种搜索方式&#xff0c;像暴力查找&#xff0c;有序数组的二分查找&#xff0c;二分查找就很快了&#xff0c;可以达到O(log n)。但是有序数组有一个 弊端&#xff0c;就是要先进行排序&#xff0c;这就有消耗&#xff0c;这还好&#xff0c;当要插入删除修改…

Go-Python-Java-C-LeetCode高分解法-第八周合集

前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接&#xff1a;LeetCode-Go-Python-Java-C 欢迎订阅CSDN专栏&#xff0c;每日一题&#xff0c;和博主一起进步 LeetCode专栏 本文部分内容来自网上搜集与个人实践。如果任何信息存在错误,欢迎…

UE5.1编辑器拓展【一、脚本化资产行为,通知,弹窗,高效复制多个同样的资产】

目录​​​​​​​ 插件制作 添加新的类&#xff1a;AssetActionUtility 添加新的模块&#xff1a;EditorScriptingUtilities 路径了解 添加debug的头文件 代码【debug.h】内涵注释&#xff1a; 写函数 .h文件 .cpp文件 插件制作 首先第一步是做一个插件&#xff1a…

Flink中序列化RoaringBitmap不同方式的对比

背景 在flink中&#xff0c;我们有时候会使用到RoaringBitmap进行统计计数等操作&#xff0c;而当使用RoaringBitmap时&#xff0c;这就涉及到了最重要的问题&#xff0c;如何序列化&#xff1f;序列化的目的是为了进行网络通信或者状态序列化的目的&#xff0c;本文的重点是比…

根据GWAS数据估算样本量N和使用千人基因组填充maf的参考文献

https://github.com/GenomicSEM/GenomicSEM/wiki/2.1-Calculating-Sum-of-Effective-Sample-Size-and-Preparing-GWAS-Summary-Statistics

【LeetCode热题100】--104.二叉树的最大深度

104.二叉树的最大深度 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) …

尚硅谷谷粒商城部分报错问题处理

1、启动报错&#xff1a; 内容&#xff1a; org.springframework.beans.factory.BeanCreationException: Error creating bean with name attrAttrgroupRelationController: Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed t…

使用prometheus监控java服务

在prometheus官方下载页面没有看到jvm_exproter的下载地址但是官方页面是有推荐下载地址的 访问 Prometheus - Monitoring system & time series database prometheus官方网址 官方推荐地址下载是在github网络访问不方便的可以用下面的网址 wget https://repo1.maven…

【小程序 - 基础】页面导航、页面事件、生命周期、WXS脚本_04

目录 一、页面导航 1. 什么是页面导航 2. 小程序中实现页面导航的两种方式 2.1 声明式导航 2.1.1 导航到 tabBar 页面 2.1.2 导航到非 tabBar 页面 2.1.3 后退导航 2.2 编程式导航 2.2.1 导航到 tabBar 页面 2.2.2 导航到非 tabBar 页面 2.2.3 后退导航 2.3. 导航…

Proxyer实现内网穿透云服务器

Proxyer Proxyer是一个网络代理工具&#xff0c;它可以将本地计算机的网络流量&#xff08;如HTTP、HTTPS、TCP等&#xff09;转发到远程服务器。使用Proxyer可以在本地计算机上建立一个代理服务器&#xff0c;通过代理服务器来访问互联网上的资源。 yum仓库设置 rm -f /etc…

在Ubuntu上通过Portainer部署微服务项目

这篇文章主要记录自己在ubuntu上部署自己的微服务应用的过程&#xff0c;文章中使用了docker、docker-compose和portainer&#xff0c;在部署过程中遇到了不少问题&#xff0c;因为博主也是初学docker-compose&#xff0c;通过这次部署实战确实有所收获&#xff0c;在这篇文章一…

LeetCode【121. 买卖股票的最佳时机】

你才不是什么小人物&#xff0c;你在我这里&#xff0c;是所有的天气和心情。 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一…

idea Springboot 校园助学贷款系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 校园助学贷款系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统 具有完整的源代码和数据库&…

小谈设计模式(8)—代理模式

小谈设计模式&#xff08;8&#xff09;—代理模式 专栏介绍专栏地址专栏介绍 代理模式代理模式角色分析抽象主题&#xff08;Subject&#xff09;真实主题&#xff08;Real Subject&#xff09;代理&#xff08;Proxy&#xff09; 应用场景远程代理虚拟代理安全代理智能引用代…

ubuntu22.04 x11窗口环境手势控制

ubuntu22.04 x11窗口环境手势控制 ubuntu x11窗口环境的手势控制并不优秀&#xff0c;我们可以使用touchegg去代替 这个配置过程非常简单&#xff0c;并且可以很容易在一定范围内达到你想到的效果&#xff0c;类比mac的手势控制 关于安装 首先添加源&#xff0c;并安装 sud…

数据结构-----二叉排序树

目录 前言 1.什么是二叉排序树 2.如何构建二叉排序树 3.二叉排序树的操作 3.1定义节点储存方式 3.2插入节点操作 3.2创建二叉排序树 3.4遍历输出&#xff08;中序遍历&#xff09; 3.5数据查找操作 3.6获取最大值和最小值 3.7删除节点操作 3.8销毁二叉排序树 4.完…

漏斗分析模型

从业务流程起点开始到最后日标完成的每个环节都会有用户流失&#xff0c;因此需要一种分析方法来衡量业务流程每一步的转化效率&#xff0c;漏斗分析方法就是这样的分析方法。 例如&#xff0c;在淘宝上一款商品的浏览量是 300、点击量是 100、订单量是 20、支付量是 10&#…

centos 部署nginx 并配置https

centos版本&#xff1a;centos 7.8 &#xff08;最好不要用8&#xff0c;8的很多用法和7相差很大&#xff09; 一.安装nginx 1。下载Nginx安装包&#xff1a;首先&#xff0c;访问Nginx的官方网站&#xff08;https://nginx.org/&#xff09;或您选择的镜像站点&#xff0c;找…