常见的几种Sort排序算法

2023-10-26

  几种常见的Sort排序算法

1. 排序的基本概念

n个记录的序列,其相应关键字的序列是,相应的下表序列是。通过排序,要求找出当前下标序列的一种排列,使得相应的关键字满足如下的非递减(或非递增)关系:,这样就得到一个按关键字有序的记录序列。该文主要是以升序为例。

2. 排序的分类

常见的Sort排序可分为如下几种:

3. 几种排序算法的具体介绍与实现

(1)直接插入排序
插入排序的基本思想是:在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入到已排好序的记录子集中,直到将所有待排记录全部插入为止。
直接插入排序的算法思想是:将第i个记录插入到前面的i-1个已排好序的记录中。
具体过程为:将第i个记录的关键字,顺序与其前面记录的关键字进行比较,将所有关键字大于的记录依次向后移动一个位置,直到遇到一个关键字小于或等于的记录,此时该记录后面一定有空位置,将第i个记录插入到该空位置即可。
代码实现:
#include 
    
    
     
     
#include 
     
     
      
      
using namespace std;

void Printf(int* a,size_t n)
{
	for (size_t i = 0; i < n; ++i)
	{
		cout << a[i] << " ";
	}
	cout << endl;
}

void InsertSort(int* a, size_t n)
{
	assert(a);
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		int tmp = a[end + 1];
		for (; end >= 0; --end)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

void TestInsertSort()
{
	int a[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
	Printf(a, sizeof(a) / sizeof a[0]);
	InsertSort(a, sizeof(a) / sizeof a[0]);
	Printf(a, sizeof(a) / sizeof a[0]);
}

     
     
    
    
运行结果:
(2)希尔排序
算法思想:希尔排序又称缩小增量排序法,是一种基于插入思想的排序方法,将待排序的关键字序列分为若干个较小的子序列,对子序列进行直接插入排序,使整个待排序列排好序。
可分为两步:(a)预排序
                        (b)插入排序
代码实现:
void ShellSort(int* a, size_t n)
{
	assert(a);
	int gap = n;
	while (gap > 1)
	{
		gap = (gap / 3) + 1;
		for (size_t i = 0; i < n-gap; ++i)
		{
			int end = i;
			int tmp = a[end + gap];
			for (; end >= 0; end -= gap)
			{
				if (a[end]>tmp)
				{
					a[end + gap] = a[end];
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}


void TestShellSort()
{
	int a[] = { 2, 5, 4, 9, 3, 6, 8, 7, 1, 0 };
	Printf(a, sizeof(a) / sizeof a[0]);
	ShellSort(a, sizeof(a) / sizeof a[0]);
	Printf(a, sizeof(a) / sizeof a[0]);
}

运行结果:


注意:当子序列记录间的间隔为d时,共有d个子序列,需要对d个子序列分别进行插入排序。在具体实现时,并不是先对一个子序列完成插入排序,再对另外一个子序列进行插入排序,而是从第一个子序列的第二个记录开始,顺序扫描整个待排序记录序列,当前记录属于哪个子序列,就在哪一个子序列中进行插入排序。(各子序列的记录将轮流出现)

(3)选择排序

算法思想:第一趟排序时,从第一个记录开始,通过n-1次关键字的比较,从n个记录中选出关键字最小记录,并和第一个记录进行交换;第二趟排序时,从第二个记录开始,通过n-2次关键字的比较,从n-1个记录中选出关键字最小记录,并和第二个记录进行交换;如此反复,经过n-1趟排序,将n-1个记录排到位,剩下的一个直接排在最后。

该方法一次选择两个记录,进行排序。


依次类推,即可完成排序。

代码实现:

void SelectSort(int* a, size_t n)
{
	assert(a);
	size_t begin = 0, end = n - 1;
	while (begin < end)
	{
		size_t min = begin, max = begin;
		for (size_t i = begin; i <= end; ++i)
		{
			if (a[i]
  
  
   
   a[max])
			{
				max = i;
			}
		}

		swap(a[begin], a[min]);
		if (begin == max)
		{
			max = min;
		}
		swap(a[end], a[max]);
		++begin;
		--end;
		
	}
}

void TestInsertSort()
{
	int a[] = { 2, 5, 4, 9, 3, 5, 8, 7, 1, 5 };
	Printf(a, sizeof(a) / sizeof a[0]);
	SelectSort(a, sizeof(a) / sizeof a[0]);
	Printf(a, sizeof(a) / sizeof a[0]);
}

  
  

运行结果:


(4)堆排序

算法思想:把待排序的记录的关键字存放在一个数组中,将其看成是一棵完全二叉树的顺序表示,每个结点表示一个记录,第一个记录作为二叉树的根,接下来依次逐层从左到右顺序排列,最终对

代码实现:

void AdjustDown(int* a, int  n, size_t root)
{
	size_t parent = root;
	size_t 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, size_t n)         //升序建大堆
{
	assert(a);
	for (int i = (n - 2) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}
	size_t end = n - 1;
	while (end > 0)
	{
		swap(a[0], a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}

void TestInsertSort()
{
	int a[] = { 2, 5, 4, 9, 3, 5, 8, 7, 1, 0 };
	Printf(a, sizeof(a) / sizeof a[0]);
	heapSort(a, sizeof(a) / sizeof a[0]);

	Printf(a, sizeof(a) / sizeof a[0]);
}

运行结果:


(5)冒泡排序

算法思想:通过对相邻的数据元素进行交换,逐步将待排序序列变成有序序列的过程。以升序为例,在第一趟冒泡排序中,从第一个记录开始,扫描整个待排序记录序列,若相邻的两个记录逆序,则交换位置,然后进行第二趟排序,对前n-1个记录进行同样的操作,其结果是使次大的记录被放在第n-1个记录的位置上。,如此反复,每一趟排序都将一个记录排到位,直到剩下一个最小的记录。若在某一趟冒泡排序过程中,没有发现一个逆序,则可直接结束整个排序过程。

代码实现:

void BubbleSort(int* a, size_t n)
{
	assert(a);
	for (size_t end = n; end > 0; --end)
	{
		size_t first = 0;
		size_t second = 1;
		while (second < end)
		{
			if (a[first]>a[second])
			{
				swap(a[first], a[second]);
			}
			++first;
			++second;
		}
	}
}

void TestInsertSort()
{
	int a[] = { 2, 5, 4, 9, 3, 5, 8, 7, 1, 0 };
	Printf(a, sizeof(a) / sizeof a[0]);
	BubbleSort(a, sizeof(a) / sizeof a[0]);

	Printf(a, sizeof(a) / sizeof a[0]);
}
运行结果:

(6)快速排序

从待排序记录序列中选取一个记录为枢轴,其关键字设为,然后将其余关键字小于的记录移到前面,而将关键字大于的记录移到后面,结果将待排序记录序列分成两个子表,最后将关键字为的记录插到其分界线的位置处。将其称为一次快速排序。

算法思想:

通过一次划分后,就以关键字为的记录为界,将待排序序列分为两个子表,且前面子表中所有的关键字均不大于,后面的均不小于。对分割后的子表按照上述原则继续进行分割,直到所有子表的表长不超过1为止,此时待排序记录序列就变成了一个有序表。


快速排序可以有以下三种方法实现:

(a)左右指针法


代码实现:

int PartSort1(int* a, int begin, int end)
{
	int key = end;
	while (begin < end)
	{
		while (begin
   
   
    
    =a[key])
		{
			--end;
		}
		if (begin < end)
		{
			swap(a[begin], a[end]);
		}
	}
	swap(a[begin], a[key]);
	return begin;
}

void QuickSort(int* a, int left, int right)
{
	assert(a);
	if (left < right)
	{
		int div = PartSort1(a, left, right);
		
		QuickSort(a, left, div - 1);
		QuickSort(a, div + 1, right);
	}
}
   
   
运行结果:


(2)挖坑法


代码实现:

//挖坑法

int PartSort2(int* a, int begin, int end)
{
	int key = a[end];
	while (begin < end)
	{
		while (begin < end && a[begin] <= key)
		{
			++begin;
		}
		if (begin
   
   
    
    = key)
		{
			--end;
		}

		if (begin
    
    
   
   
运行结果:


(3)前后指针


代码实现:

//前后指针
int PartSort3(int* a, int begin, int end)
{
	int key = end;
	int cur = begin;
	int prev = cur - 1;
	while (cur < end)
	{
		if (a[cur] < a[key] && ++prev != cur)
		{
			swap(a[prev], a[cur]);
		}
		++cur;
	}
	swap(a[++prev], a[key]);
	return prev;

}


void QuickSort(int* a, int left, int right)
{
	assert(a);
	if (left < right)
	{
		int div = PartSort3(a, left, right);

		QuickSort(a, left, div - 1);
		QuickSort(a, div + 1, right);
	}
}
运行结果:


(7)归并排序

基本思想:是基于合并,将两个或两个以上有序表合并成一个新的有序表。


代码实现:

void _Merge(int* a, int* tmp, int begin1, int end1, int begin2, int end2)
{
	int start = begin1;
	int finsh = end2;
	size_t index = begin1;
	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 + start, tmp + start,(finsh - start + 1)*sizeof(int));
}

void _MergeSort(int* a, int* tmp, int begin, int end)
{
	if (begin >= end)
		return;
	int mid = begin + (end - begin) / 2;
	_MergeSort(a, tmp, begin, mid);
	_MergeSort(a, tmp, mid + 1, end);
	_Merge(a, tmp, begin, mid, mid + 1, end);

}

void MergeSort(int* a, int n)
{
	assert(a);
	int* tmp = new int[n];
	_MergeSort(a, tmp, 0, n - 1);
	delete[] tmp;
}

void TestInsertSort()
{
	int a[] = { 2, 0, 4, 9, 3, 5, 8, 7, 1, 5 };
	Printf(a, sizeof(a) / sizeof a[0]);
	MergeSort(a, sizeof(a) / sizeof a[0]);

	Printf(a, sizeof(a) / sizeof a[0]);
}


关于几种排序的比较总结,及优化见下篇博客。




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

常见的几种Sort排序算法 的相关文章

  • WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)

    WebGL three js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图 时空隧道demo演示 Demo地址 https nsytsqdtn github io demo sprite tunnel three js的粒子系统 t
  • 一文彻底搞懂前端实现文件预览(word、excel、pdf、ppt、mp4、图片、文本)

    作者 竹业 https juejin cn post 7071598747519549454 前言 因为业务需要 很多文件需要在前端实现预览 今天就来了解一下吧 Demo地址 1 https zhuye1993 github io file
  • Linux系统查看文件的命令及作用详解

    在Linux系统中 查看文件的命令常用的有五个 分别是 find命令 locate命令 whereis命令 which命令及type命令 接下来通过这篇文章为大家详细介绍一下这五个命令 Linux查看文件的五种命令 1 find find是
  • OLED屏幕对比LCD为什么更加省电?

    OLED显示技术与传统的LCD显示方式不同 无需背光灯 采用非常薄的有机材料涂层和玻璃基板 当有电流通过时 这些有机材料就会发光 而且OLED显示屏幕可以做得更轻更薄 可视角度更大 并且能够显著节省电能 OLED的特性是自己发光 不像TFT
  • Windows Docker 端口占用错误解决

    Windows Docker 端口占用错误解决 错误来源 Error invoking remote method docker start container Error HTTP code 500 server error Ports
  • 微信小程序-配置请求域名合法的问题以及豆瓣api问题

    一 配置请求域名合法的问题 在哪里找到配置request合法域名 1 进入在微信公众平台官网首页 mp weixin qq com 微信公众平台 小程序 首页 2 右下角设置 3 开发设置 里面有AppID和服务器域名 二 豆瓣api问题
  • Windows系统缺失ieframe.dll文件如何解决?

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库 这时你可以下载这个ieframe
  • BOOST升压电路参数计算

    BOOST电路的参数计算主要包括占空比D 电感值L 电容值C 假设1 电感的电流工作在连续的状态并忽略电感的阻值 假设2 电路工作在稳定的状态 1 计算占空比D 电路稳定时 电感满足 伏秒值相等的原则 占空比D 导通状态 截止状态 考虑二极
  • Django by Example·第二章

    Django by Example 第二章 Enhancing Your Blog with Advanced Features 为博客系统添加高级功能 笔记 这本书的结构确实很不错 如果能够坚持看下去 那么Django框架的各种用法也就掌
  • Linux的Web服务器配置

    准备工作 1 准备两台虚拟机 CentOS 一台作为服务器 一台作为客户机 选择仅主机模式进行连接 2 检查是否安装好了httpd rpm q httpd 3 如果没有安装好 安装步骤 cd run media root CentOS 7
  • 【大数据】基于 Flink CDC 高效构建入湖通道

    基于 Flink CDC 高效构建入湖通道 1 Flink CDC 核心技术解析 2 CDC 数据入湖入仓的挑战 2 1 CDC 数据入湖架构 2 2 CDC 数据 ETL 架构 3 基于 Flink CDC 的入湖入仓方案 3 1 Fli
  • bigquery使用教程_如何使用Python和Google BigQuery构建机器人以自动执行您的笨拙任务...

    bigquery使用教程 Do you have repetitive tasks Something that you do regularly every week or even every day Reporting might b
  • 简谈高防CDN

    高防CDN即内容分流网络流量防御 原理就是构建在网络之上的内容分发网络 依靠部署在各地的边缘服务器 通过中心平台的负载均衡 内容分发 调度等功能模块 使用户就近获取所需内容 而不用直接访问网站源服务器 其原理简单的说就是架设多个高防CDN节
  • 2023年03月 C/C++(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

    C C 编程 1 8级 全部真题 点这里 第1题 字符长方形 给定一个字符 用它构造一个长为4个字符 宽为3个字符的长方形 可以参考样例输出 时间限制 1000 内存限制 65536 输入 输入只有一行 包含一个字符 输出 该字符构成的长方
  • 轻松记住大端小端的含义(附对大端和小端的解释)

    或许你曾经仔细了解过什么是大端小端 也动手编写了测试手头上的机器上是大端还是小端的程序 甚至还编写了大端小端转换程序 但过了一段时间之后 当你再看到大端和小端这两个字眼 你的脑中很快浮起了自己曾经做过的工作 却总是想不起究竟哪种是大端 哪种
  • Navicat连接不上sqlserver问题解决(2008R2)

    Navicat连接不上sqlserver问题解决 一 连接SQL Server时出错 未发现数据源名称并且未指定默认驱动程序 1 安装支持文件 因为没有安装连接支持文件 本身navicat其实是支持SQL server的连接的 只不过是因为
  • 目标分割、目标识别、目标检测和目标跟踪的区别

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 https www cbedai net linuxcore 1 目标分割 任务是把目标对应的部分分割出来 2 目标检测 检测到图片当中的目标的具体位置 3 目标识别 即是在所有的
  • 选择排序(Selection Sort)-- 初级排序算法

    1 选择排序 Selection Sort 选择排序 Selection sort 是一种简单直观的排序算法 它的工作原理 首先在未排序序列中找到最小 大 元素 存放到排序序列的起始位置 然后 再从剩余未排序元素中继续寻找最小 大 元素 然
  • i春秋CTF-WEB题解(一)

    简述 这次转到了i春秋平台上面练习 和之前一样也是每3道题目就写一篇题解来作为记录 一 爆破 1 百度杯CTF比赛 2017 二月场 题目给的提示是 flag就在某六位变量中 打开题目的链接 能得到一段PHP代码 大致代码解析如下 引入包含
  • C#中Thread.Time的使用

    Thread Time的使用 线程同步处理之一 这个类主要是开启一个线程 然后实现按照指定的周期 定期的调用指定的某个函数 实现了定期调用一个函数或程序的办法 比如想让一个后台程序 定期检查是否收到邮件 或者让一个后台线程定期输出当前时间等

随机推荐

  • 一文讲解单片机、 ARM、 MCU、 DSP、 FPGA、 嵌入式错综复杂的关系

    概述 一文讲解单片机 ARM MCU DSP FPGA 嵌入式错综复杂的关系 首先 嵌入式 这是个概念 准确的定义没有 各个书上都有各自的定义 但是主要思想是一样的 就是相比较PC机这种通用系统来说 嵌入式系统是个专用系统 结构精简 在硬件
  • ESP8266_12 ESP8266客户端模式下的TCP通信

    ESP8266 01搭建开发环境 ESP8266 02程序的编译与下载 ESP8266 03SDK与Makefile的基本用法 ESP8266 04管脚控制与软件定时器 ESP8266 05 ESP8266有几个串口 ESP8266 06硬
  • java 回调函数解读

    模块间调用 在一个应用系统中 无论使用何种语言开发 必然存在模块之间的调用 调用的方式分为几种 1 同步调用 同步调用是最基本并且最简单的一种调用方式 类A的方法a 调用类B的方法b 一直等待b 方法执行完毕 a 方法继续往下走 这种调用方
  • LaTex学习笔记(文档基本结构、编译与特殊符号)

    1 文章开始 文章第一句通常为 documentclass article book report letter等 documentclass x 作为文章排版的依据 x代表排版方式 基本的排版方式有 article 用于文章排版 book
  • epoll与select区别

    select和epoll的区别 面试常考 首先select是posix支持的 而epoll是linux特定的系统调用 因此 epoll的可移植性就没有select好 但是考虑到epoll和select一般用作服务器的比较多 而服务器中大多又
  • BP神经网络参数总结

    BP神经网络参数总结 BP神经网络是一种常用的人工神经网络模型 广泛应用于分类 回归和模式识别等任务中 在进行BP神经网络训练之前 需要对网络的参数进行设置和调整 以获得更好的性能和准确度 下面将对BP神经网络的参数进行总结 并给出相应的源
  • 【线程】详解线程状态(到底是五种还是六种)

    首先我们要知道 在传统 操作系统 的线程模型中线程被分为五种状态 在java线程中 线程被分为六种状态 传统线程模型 操作系统 中线程状态 线程的五种状态 1 新建 new 创建了一个新的线程对象 2 就绪 runnable 调用线程的st
  • python 置信区间_关于置信区间的完整指南和Python示例

    python 置信区间 Confidence Interval CI is essential in statistics and very important for data scientists In this article I w
  • Python Flask 搭建微信小程序后台详解

    前言 近期需要开发一个打分的微信小程序 涉及到与后台服务器的数据交互 因为业务逻辑相对简单 故选择Python的轻量化web框架Flask来搭建后台程序 因为是初次接触小程序 经过一番摸索和尝试 个人觉得的微信小程序与后台的交互有点像aja
  • 矩阵乘法测试

    对于时间的函数 gettimeofday 函数使用方法 http blog csdn net hurmishine article details 60326345 矩阵乘法测试 代码 1 为了试验简单 两个测试矩阵均为n n 当然结果也为
  • C++中的各种进制转换函数汇总

    1 在C中 按指定进制格式输出如下 include
  • shell脚本——shell函数详解

    shell脚本 shell函数详解 一 shell函数 1 shell函数的概念 2 shell函数的格式 1 函数的定义 2 调用函数的方法 3 函数返回值 4 函数传参 5 函数变量的作用范围 6 递归 函数调用自己本身的函数 1 阶乘
  • 【MFC】列表视图控件——List Control

    01 文章目录 文章目录 01 文章目录 02 List Control介绍 03 List Control的通知消息 04 List Control的相关结构体 05 List Control的创建 06 CListCtrl类的主要成员函
  • 0-1背包问题

    题目描述 有n件物品和一个容量为v的背包 第i件物品的重量是w i 价值是p i 求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量 且价值和最大 算法分析 动态规划的题目一直是比较有难度 这种题目炸看往往连个思路都没有 往往需要数
  • expect 使用实例

    自动登录一台 服务器 代码 root localhost D151SP160 cat test1 exp bin expect set timeout 2 set user name lindex argv 0 set mypassword
  • Delphi转Java开发的辛酸

    工作已经快两年了 回想起以前的选择 真是让人不是滋味啊 通过近段时间的仔细思考和对自己以后职业规划 现在越来越想往JAVAWEB方向发展 想了许久 我还是决定辞职 放弃现在这份安逸的工作 易然的选择做JAVA这边道路 今天刚刚出来面试 就让
  • 数据结构-哈希-哈希表实现

    哈希表实现 一 哈希概念 哈希概念 常见哈希函数 哈希冲突 哈希冲突的解决 二 闭散列实现 闭散列的结构 插入 查找 删除 闭散列总结 三 哈希桶实现 哈希桶的结构 插入 查找 删除 析构 拷贝构造 赋值运算符重载 四 哈希表总结 开散列与
  • 安装windows版caffe

    MATLAB操作caffe框架 安装之前先谈谈我的电脑硬件配置 Qudra K600 的GPU 计算能力是3 0 你在安装之前也要搞清楚自己的GPU显卡是什么 看看到底支持不支持CUDA 如果支持 要查查计算能力是多少 后面配置参数要用到
  • windows环境下查看Python的安装路径

    1 windows r 进入cmd命令 2 查看python安装路径 where python
  • 常见的几种Sort排序算法

    几种常见的Sort排序算法 1 排序的基本概念 有n个记录的序列 其相应关键字的序列是 相应的下表序列是 通过排序 要求找出当前下标序列的一种排列 使得相应的关键字满足如下的非递减 或非递增 关系 这样就得到一个按关键字有序的记录序列 该文