【C++实现插入排序、希尔排序、冒泡排序、快速排序、选择排序】

news2024/11/23 8:57:01

使用C++实现来插入排序、希尔排序、冒泡排序、快速排序、选择排序算法。

一、插入排序

插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而生成一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动 。

插入排序的工作方式像许多人排序一手扑克牌。开始时,我们的左手为空并且桌子上的牌面向下。然后,我们每次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的,原来这些牌是桌子上牌堆中顶部的牌 。

插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序 。

#include<iostream>
using namespace std;

int main()
{
	int arr[6]={9,7,6,5,4,3};
	//遍历数组,依次进行比较 
	for(int i=0;i<5;i++){
		/*
		比较i和i+1,如果升序排序,则判断第i个元素是否大于第i+1个
		元素,如果是,则将第i+1个元素依次与之前的所有元素进行比较并
		排序,完成后将第i个元素插入到第i+1个元素的位置上。降序也是
		同样的原理。 
		*/ 
		if(arr[i]>arr[i+1]){
			//交换
			//从第i个元素开始交换 
			int j=i;
			//将需要插入的元素使用变量temp保存 
			int temp=arr[i+1];
			/**
			将第i个元素之前的所有元素进行一次重新排序,保证第0-i个元素
			之间是排好序的。 
			*/ 
			while(j>=0&&temp<arr[j]){
				arr[j+1]=arr[j];
				j--;
			}
			arr[j+1]=temp;
		}
	}
	//打印输出排序结果 
	for(int i=0;i<6;i++){
		cout<<arr[i]<<" ";
	}
 } 

二、希尔排序

希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。

#include<iostream>
using namespace std;

int main()
{
	int arr[6]={9,7,6,5,4,3};
	//控制步长 
	for(int gap=6/2;gap>0;gap/=2){
		//遍历所有的组 
		for(int i=0;i<gap;i++){
			//遍历每个组中的所有元素 
			for(int j=i-gap;j>=0;j-=gap){
				/*
				比较第j个元素和第j+gap个元素,不满足排序规则的交换
				元素顺序。 
				*/ 
				if(arr[j]>arr[j+gap]){
					int t=arr[j];
					arr[j]=arr[j+gap];
					arr[j+gap]=t;
				}
			}
		}
	} 
	//打印输出排序结果 
	for(int i=0;i<6;i++){
		cout<<arr[i]<<" ";
	}
 } 

三、冒泡排序

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

冒泡排序算法的原理如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
#include <iostream>
using namespace std;

int main()
{
    int array[8] = {8,7,6,5,4,3,2,1};
    //打印输出排序前的数组 
    cout<<"排序前的数组为:";
    for (int i = 0; i < 8; i++){
        cout<<array[i]<<" ";
    }
    //冒泡排序 
    for(int i=0;i<8;i++){
    	for(int j=0;j<8-1-i;j++){ 
    		if(array[j]>array[j+1]){
    			int temp=array[j];
    			array[j]=array[j+1];
    			array[j+1]=temp;
			}
		}
	}
    //打印输出排序后的数组 
    cout<<"\n排序后的数组为:";
    for (int i = 0; i < 8; i++){
        cout<<array[i]<<" ";
    }
    
    return 0;
}

四、快速排序

快速排序算法通过多次比较和交换来实现排序,其排序流程如下:

(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。

(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。

(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。

(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
原理

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它左边,所有比它大的数都放到它右边,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:

1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;

5)重复第3、4步,直到ij; 3、4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,ij这一过程一定正好是i++或j–完成的时候,此时令循环结束。

排序演示

假设一开始序列{xi}是:5,3,7,6,4,1,0,2,9,10,8。

此时,ref=5,i=1,j=11,从后往前找,第一个比5小的数是x8=2,因此序列为:2,3,7,6,4,1,0,5,9,10,8。

此时i=1,j=8,从前往后找,第一个比5大的数是x3=7,因此序列为:2,3,5,6,4,1,0,7,9,10,8。

此时,i=3,j=8,从第8位往前找,第一个比5小的数是x7=0,因此:2,3,0,6,4,1,5,7,9,10,8。

此时,i=3,j=7,从第3位往后找,第一个比5大的数是x4=6,因此:2,3,0,5,4,1,6,7,9,10,8。

此时,i=4,j=7,从第7位往前找,第一个比5小的数是x6=1,因此:2,3,0,1,4,5,6,7,9,10,8。

此时,i=4,j=6,从第4位往后找,直到第6位才有比5大的数,这时,i=j=6,ref成为一条分界线,它之前的数都比它小,之后的数都比它大,对于前后两部分数,可以采用同样的方法来排序。

#include <iostream>
 
using namespace std;
 
void Qsort(int arr[], int low, int high){
    if (high <= low){
    	return;
	}
	
    int left = low;
    int right = high;
    int key = arr[low];
    
    while (true)
    {
        //将比key小的值放key左边,比key大的值放key右边 
		/*从左向右找比key大的值*/
        while (arr[left] <= key)
        {
            left++;//从左往右,下标递增 
            //当遍历到最后一个元素时,结束循环 
            if (left == high){
                break;
            }
        }
        /*从右向左找比key小的值*/
        while (arr[right] >= key)
        {
            right--; //从右往左,下标递减 
            //当遍历到第一个元素时,结束循环 
			if (right == low){
                break;
            }
        }
//        cout<<"left:"<<left<<" right:"<<right<<"\n"; 
        /*
		当比key小的数全在左边,比key大的数全在右边时,表
		示第一次排序完成,结束循环
		*/ 
		if (left >= right){
        	break;
		}
        /*
		将比key小的数移到左边,比key大的数移到右边,
		交换left,right对应的值
		*/
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
    }
    /*分别对左右两边的数字进行排序,
	中枢值与right对应值交换*/
    arr[low] = arr[right];
    arr[right] = key;
    Qsort(arr, low, right - 1);
    Qsort(arr, right + 1, high);
}
 
int main()
{
    int arr[] = {52, 64, 59, 52, 75, 28, 98, 30, 25};
    //获取数组长度 
	int len = sizeof(arr)/sizeof(arr[0]); 
	//打印排序前的数组
	cout<<"排序前:"; 
    for(int i = 0; i < len; i++)
    {
        cout << arr[i] << " ";
    }
    //调用快速排序函数 
	Qsort(arr, 0, len- 1);
	//打印排序后的数组 
    cout<<"\n排序后:";
    for(int i = 0; i < len; i++)
    {
        cout << arr[i] << " ";
    }
    return 0;
}

五、选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

排序思路:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

具体实现方法

①初始状态:无序区为R[0…n-1](共n个元素),有序区为空。

②第1趟排序

设置一个变量i,让i从0至n-2循环的同时,在对比数组中元素i跟元素i+1的大小,如果R[i+1]比R[i]小,则用一个变量k来记住他的位置(即k=i+1)。等到循环结束的时候,我们应该找到了R中最小的那个数的位置了。然后进行判断,如果这个最小元素的不是R的第一个元素,就让第一个元素跟他交换一下值,使R[0…0]和R[1…n-1]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

……

③第i趟排序

第i趟排序开始时,当前有序区和无序区分别为R[0…i-1]和R[i…n-1]。该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[0…i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

图1例子:(通过寻找最小值的选择排序)

图1 选择排序(最小值)实例

#include<iostream>

using namespace std;

/*遍历寻找当前序列中的最小值,返回最小值的下标*/
int selectMin(int arr[],int i,int len){
	int min=i;
	for(;i<len;i++){
		if(arr[i]<arr[min]){
			min=i;
		}
	}
	return min;
}

int main()
{
	int arr[]={5,8,2,4,1,6};
	int len=sizeof(arr)/sizeof(arr[0]);
	for(int i=0;i<len;i++){
        //接收当前序列的最小值下标
		int j=selectMin(arr,i,len);
		//判断最小值是否为当前元素,如果不是,则交换最小值和当前元素的位置
        if(i!=j){
			int temp=arr[i];
			arr[i]=arr[j];
			arr[j]=temp;
		}
	}
	for(int i=0;i<len;i++){
		cout<<arr[i]<<" ";
	}
  }  

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

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

相关文章

2023爱分析·中国面向开发者的低代码开发平台市场厂商评估报告

01 研究范围定义 “低代码”是一种可视化的应用开发方式&#xff0c;相对于传统编写代码的“纯代码”开发方式&#xff0c;低代码开发平台可以减少代码编写量或不使用代码编写进行应用的开发。随着技术革新&#xff0c;大模型也为低代码开发平台发展指明了新方向。从开发者与开…

单片机GD32F303RCT6 (Macos环境)开发 (二十八)—— 蓝牙透传模块HC-08 Android App开发

蓝牙透传模块HC-08 Android App开发 1、App整体开发思路 a、首先要申请权限&#xff0c;采用动态申请的方式&#xff0c;用户点击确认后方可操作蓝牙。 b、搜索蓝牙&#xff0c;之前的版本用startLeScan函数搜索蓝牙&#xff0c;虽然高版本中依然可用&#xff0c;但是google已…

什么时候该停止使用Scrum?

01、TL;DR:一个团队什么时候应该停止使用Scrum? 什么时候才能超越Scrum?毕竟许多类似思想、实践等事务迟早会过时;那为什么Scrum会是个例外?此外&#xff0c;我们不是通过实践Scrum来获得报酬&#xff0c;而是在既定的约束条件下解决客户的问题&#xff0c;同时又能为组织的…

( 链表) 707. 设计链表 ——【Leetcode每日一题】

❓707. 设计链表 难度&#xff1a;中等 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还…

ubuntu 安装ffmpeg

一、我的编译环境 ubuntu 22 ffmpeg 4.36 二、安装必要的依赖 sudo apt-get update sudo apt-get install -y \autoconf \automake \build-essential \cmake \git-core \libass-dev \libfreetype6-dev \libsdl2-dev \libtool \libva-dev \libvdpau-dev \libvorbis-dev \lib…

160743-62-4,DMG PEG2000,1,2-二肉豆蔻酰-rac-甘油-3-甲氧基聚乙二醇2000

DMG PEG2000&#xff0c;DMG-mPEG2000&#xff0c;1,2-二肉豆蔻酰-rac-甘油-3-甲氧基聚乙二醇2000 Product structure&#xff1a; Product specifications&#xff1a; 1.CAS No&#xff1a;160743-62-4 2.Molecular formula&#xff1a; C34H66O 3.Molecular weight&#xff…

Ubuntu18.04 dash to dock启动器安装教程

1.安装主题工具&#xff1a;GNOME Tweaks sudo apt-get update sudo apt-get install gnome-tweak-tool2.手动安装dash-to-dock插件 Dash-to-dock不支持3.32以上版本的gnome&#xff0c;git clone dash to dock的仓库 yeatsyeats-virtual-machine:~/Tools$ git clone https:/…

Axure教程—垂直方向多色图(中继器)

本文将教大家如何用AXURE制作动态垂直方向多色图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://9fxtte.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87822547?spm1001.2014.3001.5503 二、功能介绍 简单填写中继…

mfc100.dll丢失如何解决?修复mfc100.dll的方法分享

mfc100.dll是Microsoft Visual C 2010中的一个动态链接库文件。如果该文件丢失&#xff0c;将会导致某些应用程序无法正常运行。在本文中&#xff0c;我们将探讨关于mfc100.dll丢失的问题&#xff0c;以及如何解决它。 一.什么是mfc100.dll mfc100.dll是Microsoft Visual C 20…

头羊部落亮相第26届北京餐食会

第26届AIFE2023亚洲&#xff08;北京&#xff09;国际食品饮料暨餐饮食材展览会&#xff08;简称&#xff1a;BCFE北京餐食会) 于2023年5月23-25日在北京中国国际展览中心火热召开。顺应时代发展下的餐饮新潮流&#xff0c;北京餐食会首次聚焦预制菜市场&#xff0c;为彰显预制…

Web安全:代码执行漏洞 测试.

Web安全&#xff1a;代码执行漏洞 测试 攻击者可以通过构造恶意输入来欺骗应用程序执行恶意代码。这种漏洞通常出现在应用程序中使用动态语言(如 PHP、Python、Ruby 等)编写的代码中&#xff0c;因为这些语言允许在运行时动态执行代码。攻击者可以通过构造特定的输入来欺骗应用…

分布式事务的21种武器 - 5

在分布式系统中&#xff0c;事务的处理分布在不同组件、服务中&#xff0c;因此分布式事务的ACID保障面临着一些特殊难点。本系列文章介绍了21种分布式事务设计模式&#xff0c;并分析其实现原理和优缺点&#xff0c;在面对具体分布式事务问题时&#xff0c;可以选择合适的模式…

经典组件知识(zookeeper,kafka,ngix)

关于zookeeper的具体介绍 优化的点可以在于zookeeper吗&#xff1f; 如何安装使用&#xff1f; #include <zookeeper/zookeeper.h> 1、先配置java环境JDK&#xff0c;因为需要用java编译&#xff1b; 2、下载zk源码&#xff0c;解压&#xff1b; 3、重命名配置文件zoo_sa…

5000 字手把手实战|Kubernetes+极狐GitLab CI,获得极致 CI/CD 体验

目录 极狐GitLab CI K8s 架构解析 极狐GitLab CI 流程图 流程详解 极狐GitLab CI K8s 架构优点 开启极狐GitLab CI K8s 实战 环境准备 记录注册信息 获取极狐GitLab Runner 绑定 docker.sock 配置缓存 安装极狐GitLab Runner 集成 CI 定义文件 注意事项 配置…

Python实战基础11-函数

1 函数的创建于调用 1.1 创建一个函数 创建函数也称为定义函数&#xff0c;定义函数的格式如下&#xff1a; def functionname([parameterlist]): [comments] [functionbody] 参数说明&#xff1a; functionname&#xff1a;函数名称&#xff0c;在调用函数时使用。 paramete…

用echarts绘制的柱状图、折柱结合图,源码文末免费拿!

文章目录 Apache EchartsNPM 安装 ECharts在线定制 ECharts使用 Echarts 绘制基础柱状图绘制带背景的柱状图绘制带背景的柱状图绘制多条柱状图绘制条形柱状图绘制带标记的柱状图绘制折线图和柱状图绘制多轴折线图和柱状图源码地址 Apache Echarts 本文中的所有代码&#xff0c…

剑指offer(C++)-JZ46:把数字翻译成字符串(算法-动态规划)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 有一种将字母编码成数字的方式&#xff1a;a->1, b->2, ... , z->26。 现在给一串数字&#xf…

如何在Angular应用程序中插入自定义 CSS?这里有答案!

Kendo UI for Angular是专用于Angular开发的专业级Angular组件&#xff0c;telerik致力于提供纯粹的高性能Angular UI组件&#xff0c;无需任何jQuery依赖关系。 Kendo UI R1 2023正式版下载(Q技术交流&#xff1a;726377843&#xff09; 为什么需要在 Angular 应用程序中插入…

兼容性测试点和注意项,建议收藏

一&#xff1a;兼容性测试的概念&#xff1a;就是验证开发出来的程序在特定的运行环境中与特定的软件、硬件或数据相组合是否能正常运行、有无异常的测试过程。 二&#xff1a;兼容性测试的分类&#xff1a; &#xff08;1&#xff09;浏览器兼容性测试 指的是在浏览器上检查…

航空公司预订票数学建模论文

航空公司预订票数学建模论文篇1 试谈机票订票模型与求解 一、概述 1. 问题背景描述 在激烈的市场竞争中&#xff0c;航空公司为争取更多的客源而开展的一个优质服务项目是预订票业务,本模型针对预订票业务&#xff0c;建立二元规划订票方案&#xff0c;既考虑航空公司的利润最大…