排序(七种排序)

news2024/11/16 23:49:50

1.插入排序

2.希尔排序

3.选择排序
4.堆排序
5.冒泡排序
6.快速排序
7.归并排序

 

 1.插入排序

        1.1思路

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列  

 

        1.2实现 

//插入排序
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		// [0, end] 有序,插入tmp依旧有序
		int end = i;
		int tmp = a[i + 1];

		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}

		a[end + 1] = tmp;
	}
}

2. 希尔排序

        2.1思路

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

        2.2实现 

void ShellSort(int* a, int n)
{
	// 1、gap > 1 预排序
	// 2、gap == 1 直接插入排序

	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;  // +1可以保证最后一次一定是1
		// gap = gap / 2;
		for (int i = 0; i < n - gap; ++i)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}

			a[end + gap] = tmp;
		}
	}
}

3. 选择排序

        3.1思路

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完

  

        3.2实现 

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void SelectSort(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
        //找出最大和最小值放在开头和结尾,然后begin++,end--
		int maxi = begin, mini = begin;
		for (int i = begin; i <= end; i++)
		{
			if (a[i] > a[maxi])
			{
				maxi = i;
			}

			if (a[i] < a[mini])
			{
				mini = i;
			}
		}

		Swap(&a[begin], &a[mini]);
		// 如果maxi和begin重叠,修正一下即可
        //如果maxi和begin重叠,可能会重复交换
		if (begin == maxi)
		{
			maxi = mini;
		}

		Swap(&a[end], &a[maxi]);

		++begin;
		--end;
	}
}

 4.堆排序

        4.1思路

堆排序 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
不知道堆的可以参考: 数据结构:堆的实现_元清加油的博客-CSDN博客

        4.2实现 

//向下调整法
void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 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 = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// 排升序
void HeapSort(int* a, int n)
{
	// 建大堆
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}
    //堆删除的思想
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}

5.冒泡排序 

         5.1思路

冒泡排序非常的简单,相邻二个数比较大小,然后交换即可

        5.2实现 

void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n; ++j)
	{
		bool exchange = false;
		for (int i = 1; i < n - j; i++)
		{
			if (a[i - 1] > a[i])
			{
				int tmp = a[i];
				a[i] = a[i - 1];
				a[i - 1] = tmp;

				exchange = true;
			}
		}

		if (exchange == false)
		{
			break;
		}
	}
}

6.快速排序 

6.1霍尔快排法

        6.1.1思路

取第一个数为key,从左右出发,右边找小于key的数,左边找大于key的数,找到交换。直到左边大于右边,就交换key和左边的数

 

6.1.2 实现

void Swap(int* str1, int* str2)
{
	int temp = *str1;
	*str1 = *str2;
	*str2 = temp;
}
int PartSort1(int* a, int left, int right)
{
	int keyi = left;
	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= a[keyi])
		{
			--right;
		}

		// 左边找大
		while (left < right && a[left] <= a[keyi])
		{
			++left;
		}

		Swap(&a[left], &a[right]);
	}

	Swap(&a[keyi], &a[left]);

	return left;
}

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

	int keyi = PartSort2(a, begin, end);
	// [begin, keyi-1] keyi [keyi+1, end]

	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
}
int main()
{
	int arr[] = { 6,1,2,7,9,3,4,5,10,8 };
	QuickSort(arr, 0, 9);
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

6.2挖坑法 

6.2.1思路

取第一个数为key,从左右出发,右边找小于key的数,把他设立为一个坑位,左边找大于key的数,把他设立为一个新的坑位。直到左边大于右边,就交换key和坑的数

 

6.2.2实现 

// 挖坑法
// [left, right]
int PartSort2(int* a, int left, int right)
{
	int key = a[left];
	int hole = left;
	while (left < right)
	{
		// 右边找小
		while (left < right && a[right] >= key)
		{
			--right;
		}

		a[hole] = a[right];
		hole = right;

		// 左边找大
		while (left < right && a[left] <= key)
		{
			++left;
		}

		a[hole] = a[left];
		hole = left;
	}

	a[hole] = key;

	return hole;
}


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

	int keyi = PartSort2(a, begin, end);
	// [begin, keyi-1] keyi [keyi+1, end]

	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
}
int main()
{
	int arr[] = { 6,1,2,7,9,3,4,5,10,8 };
	QuickSort(arr, 0, 9);
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

6.3前后指针法 

6.3.1思路

取第一个数为key,初始时,prev指针指向序列开头,cur指针指向prev后一个位置。cur找小与key的数与(prev++)交换

 

6.3.2实现

// 前后指针法
// [left, right]
int PartSort3(int* a, int left, int right)
{
	int prev = left;
	int cur = left + 1;
	int keyi = left;
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			Swap(&a[prev], &a[cur]);
		}

		++cur;
	}

	Swap(&a[prev], &a[keyi]);
	keyi = prev;
	return keyi;
}
void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;

	int keyi = PartSort2(a, begin, end);
	// [begin, keyi-1] keyi [keyi+1, end]

	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
}
int main()
{
	int arr[] = { 6,1,2,7,9,3,4,5,10,8 };
	QuickSort(arr, 0, 9);
	for (int i = 0; i < 9; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

 7.归并排序

7.1思路

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法(Divide andConquer) 的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并

 

7.2实现 

//归并排序
void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin == end)
		return;
	int mid = (begin + end) / 2;
	// [begin, mid] [mid+1, end]
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid + 1, end, tmp);
	// 归并两个区间
	// ...

	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = 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);

	_MergeSort(a, 0, n - 1, tmp);

	free(tmp);
}

 

 

 

 

 

 

 

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

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

相关文章

[计算机入门] 个性化设置系统

3.2 个性化设置系统 在Windows系统中&#xff0c;个性化设置可以让用户根据自己的喜好和需求对系统进行定制和调整&#xff0c;包括桌面背景、声音、屏幕保护程序、鼠标指针、字体等。通过个性化设置&#xff0c;用户可以创建自己的独特界面和用户体验&#xff0c;使系统更加符…

HBuilderX获取iOS证书的打包步骤

简介&#xff1a; 目前app开发&#xff0c;很多企业都用H5框架来开发&#xff0c;而uniapp又是这些h5框架里面最成熟的&#xff0c;因此hbuilderx就成为了开发者的首选。然而,打包APP是需要证书的&#xff0c;那么这个证书又是如何获得呢&#xff1f; 生成苹果证书相对复杂一些…

Hyper-V Linux服务器安装

官方文档&#xff1a;在 Windows 10 创意者更新上使用 Hyper-V 创建虚拟机 | Microsoft Learn 1 新增虚拟交换机 打开Hyper-V管理器&#xff0c;找到右侧的操作列&#xff0c;点击“虚拟交换机管理器”&#xff1a; 点击“新建虚拟网络交换机”&#xff0c;交换机类型选择“外部…

用idea解决代码合并冲突

参考文章&#xff1a; IDEA&#xff1a;idea中的Git冲突解决&#xff08;非常重要&#xff09; idea操作git时 合并分支解决冲突 一、前言 1.什么事冲突&#xff1f; 冲突是指当你在提交或者更新代码时被合并的文件与当前文件不一致。读起来有点绕&#xff0c;结合下面的案例…

16、Flink 的table api与sql之连接外部系统: 读写外部系统的连接器和格式以及FileSystem示例(1)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

Unity解决:3D开发模式第三人称视角 WASD控制角色移动旋转 使用InputSystem

Unity版本&#xff1a;2019.2.3f1 目录 安装InputSystem 1&#xff1a;创建InputHander.cs脚本 挂载到Player物体上 获取键盘输入WADS 2.创建PlayerLocomotion.cs挂载到Player物体上&#xff0c;控制物体移动转向 安装InputSystem 菜单栏/Window/Package Manager/Input Syst…

AI图片处理功能演示

例如&#xff0c;这是一张不错的图片&#xff0c;但是有3只手。 我们可以选择有问题的区域&#xff0c;然后要求 niji 进行重新绘制。 根据我们选择的区域&#xff0c;我们可以以不同的方式修复结果。 创意修复 修复并不仅限于纠正错误。我们可以要求 niji 添加额外的元素&…

MATLAB R2023a for Mac Update_5

MATLAB是一种高级的计算机编程环境和开发工具&#xff0c;主要用于数值计算、数据分析、算法开发和可视化。它由MathWorks公司开发&#xff0c;被广泛应用于科学研究、工程设计、数据分析和教育等领域。 MATLAB提供了丰富的数学和工程函数库&#xff0c;可以进行矩阵运算、信号…

跨域资源共享 (CORS) | PortSwigger(burpsuite官方靶场)【万字】

写在前面 在开始之前&#xff0c;先要看看ajax的局限性和其他跨域资源共享的方式&#xff0c;这里简单说说。 下面提到大量的origin&#xff0c;注意区分referer&#xff0c;origin只说明请求发出的域。 浏览器的同源组策略&#xff1a;如果两个 URL 的 protocol、port 和 h…

所见即所得,「Paraverse平行云」助力万间打造智能建造新图景

在城市建设行业中&#xff0c;数字化逐渐成为其主导力量。 新一代信息基础设施建设也迎来了新的里程碑。数据显示&#xff0c;截至今年&#xff0c;我国已全面推进城市信息模型&#xff08;CIM&#xff09;基础平台建设&#xff0c;为城市规划、建设管理提供了多场景应用的强大…

【Python】代理池针对ip拦截破解

代理池是一种常见的反反爬虫技术&#xff0c;通过维护一组可用的代理服务器&#xff0c;来在被反爬虫限制的情况下&#xff0c;实现数据的爬取。但是&#xff0c;代理池本身也面临着被目标网站针对ip进行拦截的风险。 本文将详细介绍代理池针对ip拦截破解的方法&#xff0c;包含…

小研究 - Android 字节码动态分析分布式框架(三)

安卓平台是个多进程同时运行的系统&#xff0c;它还缺少合适的动态分析接口。因此&#xff0c;在安卓平台上进行全面的动态分析具有高难度和挑战性。已有的研究大多是针对一些安全问题的分析方法或者框架&#xff0c;无法为实现更加灵活、通用的动态分析工具的开发提供支持。此…

colab释放GPU显存

不用其他博客说的安装包&#xff0c;然后查看进程&#xff0c;kill&#xff0c;本文介绍一种简单的方法。 点击运行过代码的ipynb页面右上角的下三角&#xff0c;然后点击展开菜单栏中的View resources 随后会展开一个侧边栏&#xff0c;点击 manage sessions 3. 在页面中央会…

十问华为云 Toolkit:开发插件如何提升云上开发效能

众所周知&#xff0c;桌面集成开发环境&#xff08;IDE&#xff09;已经融入到开发的各个环节&#xff0c;对开发者的重要性和广泛度是不言而喻的&#xff0c;而开发插件更是建立在IDE基础上的功能Buff。 Huawei Cloud ToolKit作为华为云围绕其产品能力向开发者桌面上的延伸&a…

CentOS系统环境搭建(十六)——es7安装ik分词器(纯命令行安装)

centos系统环境搭建专栏&#x1f517;点击跳转 关于Elasticsearch的安装请看CentOS系统环境搭建&#xff08;十二&#xff09;——CentOS7安装Elasticsearch。 es7安装ik分词器&#xff08;纯命令行安装&#xff09; 1.找版本 我的Elasticsearch是7.17.6的&#xff0c;下载ik…

BBS项目day03、首页(前端文章布局、分类布局、标签布局)、个人站点(前后端实现)、在admin中模拟数据先在admin.py中注册表

一、首页 路由 from django.contrib import admin from django.urls import path, re_path from app01 import views from django.views.static import serve from django.conf import settingsurlpatterns [path(admin/, admin.site.urls),# 注册path(register/, views.reg…

高忆管理:降息是什么意思?降息对股市是利好还是利空?

降息和降准是比较常见的两种货币政策&#xff0c;政府通过它们来完成一定的经济目标&#xff0c;那么&#xff0c;降息是什么意思&#xff1f;降息对股市是利好仍是利空&#xff1f;下面高忆管理为大家预备了相关内容&#xff0c;以供参阅。 降息通常是指央行下降银行的存款、贷…

工时管理魔法课堂:如何在Jira中进行项目时间与成本管理?

工时管理是项目过程管理的一个重要手段&#xff0c;通过科学记录项目组成员在项目执行过程中的任务完成和时间消耗情况&#xff0c;可以帮助管理者精准评估成员工作效率&#xff0c;实时掌握项目进展&#xff0c;并有效管控项目成本。 想成为时间管理大师吗&#xff1f;与 Atl…

成集云 | Gitlab触发事件同步企微通知 | 解决方案

源系统成集云目标系统 方案介绍 GitLab是一个用于仓库管理的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建Web服务。它由GitLab Inc.开发&#xff0c;基于Ruby on Rails构建&#xff0c;并具有wiki和issue跟踪功能。GitLab主要针对软件…

动态内存管理详解

动态内存管理 1.前言 目前来回顾一下想要在内存中开辟空间有哪些方法&#xff1f; 创建变量&#xff1a; int a 0;//在栈上开辟了4字节的空间创建数组&#xff1a; int arr[10] { 0 };//在栈上开辟40字节的空间 但是这两种开辟方式都有两个特点&#xff1a; 开辟的内存空间…