排序算法学习

news2024/10/3 2:14:39

文章目录

  • 前言
  • 一、直接插入排序算法
  • 二、折半插入排序算法
  • 三、2路插入排序算法
  • 四、快速排序算法学习


前言

算法是道路生涯的一个巨大阻碍。今日前来解决这其中之一:有关的排序算法,进行实现以及性能分析。


一、直接插入排序算法

插入排序算法实现主要思想是将数据按照一定的顺序一个一个的插入到有序的表中,最终得到的序列就是已经排序好的数据。采用的方法是:在添加新的记录时,使用顺序查找的方式找到其要插入的位置,然后将新记录插入。

直接上代码实现下,学习代码比学习概念容易的多。
代码例子:对一个数组中的元素最终按照从小到大的顺序排列输出出来。

#include<stdio.h>
//自定义的输出函数
void print(int a[],int n,int i)
{
	printf("%d:",i);
	for(int j=0;j<8;j++)
	{
		printf("%d",a[j]);
	}
	printf("\n");
}
//直接插入排序函数
void InsertSort(int a[],int n)
{
	for(int i=1;i<n;i++)
	{
		if(a[i]<a[i-1])//若第i个元素大于i-1元素则直接插入;反之,需要找到适当的插入位置后在插入
		{
			int j=i-1;
			int x=a[i];
			while(j>-1 && x<a[j])//采用顺序查找方式找到插入的位置,在查找的同时,将数组中的元素进行后移操作,给插入元素腾出空间。
			{
				a[j+1]=a[j];
				j--;
			}
			a[j+1]=x;
		}
		print(a,n,i);
	}
}
int main()
{
	int a[4]={3,1,7,5};
	InsertSort(a,4);
}

在这里插入图片描述

写完了代码也差不多了解了直接插入排序算法。比如上面我们写的代码实例是按照从小到大的顺序排序。
实现的时候,遍历所有元素,看看这个元素要插入的位置的前一个元素是否比它小,如果是的话直接插入。否则,,采用顺序遍历查找,向前遍历寻找这个元素要插入的位置,并且将数组中的元素都进行后移操作,给这个要插入的元素腾出空间。(元素的整体后移)
时间复杂度O(n^2)

二、折半插入排序算法

#include<stdio.h>
void print(int a[],int n,int i)
{
	printf("%d:",i);
	for(int j=0;j<n;j++)
	{
		printf("%d",a[j]);
	}
	printf("\n");
}
void BInsertSort(int a[],int size)
{
	int i,j,low=0,high=0,mid;
	int temp=0;
	for(i=1;i<size;i++)
	{
		low=0;
		high=i-1;
		temp=a[i];
		//采用折半查找法判断插入的位置,最终变量low表示插入位置
		while(low<=high)
		{
			mid=(low+high)/2;
			if(a[mid]>temp)
			{
				high=mid-1;
			}
			else
			{
				low=mid+1;
			}
		}
		//有序表中插入位置后的元素统一后移
		for(j=i;j>low;j--)
			a[j]=a[j-1];
		a[low]=temp;
		print(a,8,i);
	}
}
int main()
{
	int a[8]={3,1,7,5,2,4,9,6};
	BInsertSort(a,8);
}

这其实就是把上面的直接遍历换成了二分法寻找
折半插入排序算法相比较于直接插入排序 算法,只是减少了关键字间的比较次数,而记录的移动次数没有进行优化,所以时间复杂度仍然是O(n^2);

三、2路插入排序算法

2-路插入排序算法的具体实现思路为:另外设置一个同存储记录的数组大小相同的数组d,将无序表中第一记录添加进d[0]的位置上,然后从无序表中第二个记录开始,同的d[0]做比较:如果该值比d[0]大,则添加到其右侧;反之添加到其左侧。

接着用上面代码进行改版:

#include<stdio.h>
#include<stdlib.h>
void insert(int arr[],int temp[],int n)
{
	int i,first,final,k;
	first=final=0; //分别记录temp数组中最大值和最小值的位置
	temp[0]=arr[0];
	for(i=1;i<n;i++)
	{
		//待插入元素比最小的元素小
		if(arr[i]<temp[first])
		{
			first=(first-1+n)%n;
			temp[first]=arr[i];
		}
		//待插入元素比最大元素大
		else if(arr[i]>temp[final])
		{
			final=(final+1+n)%n;
			temp[final]=arr[i];
		}
		//插入元素比最小大,比最大小
		else
		{
			k=(final+1+n)%n;
			//当插入值比当前值小时,需要移动当前值的位置
			while(temp[((k-1)+n)%n]>arr[i])
			{
				temp[(k+n)%n]=temp[(k-1+n)%n];
				k=(k-1+n)%n;
			}
			//插入该值
			temp[(k+n)%n]=arr[i];
			//因为最大值的位置改变,所以需要实时更新final的位置
			final=(final+1+n)%n;
			
		}
	}
	//将排序记录复制到原来的顺序表里
	for(k=0;k<n;k++)
		arr[k]=temp[(first+k)%n];
}
int main()
{
	int a[8]={3,1,7,5,2,4,9,6};
	int temp[8];
	insert(a,temp,8);
	for(int i=0;i<8;i++)
		printf("%d",a[i]);
	return 0;
}

在这里插入图片描述

四、快速排序算法学习

快速排序算法实现的基本思想是:通过一次排序将整个无序表分成相互独立的两部分,其中一部分中的数据都比另一部分中包含的数据的值小,然后继续沿用此方法分别对两部分进行同样的操作,直到每一个小部分不可再分,所得到的整个序列就成为了有序序列。
具体步骤如下:
(1)先从数列中取出一个元素作为基准数
(2)扫描数列,将比基准数小的元素全部放到它的左边,大于或等于基准数的元素全部放到它的右边,得到左右两个区间。
(3)再对左右区间重复第二步,直到各区间少于两个元素。
接下来通过图片展示一次这个步骤,相信剩下的应该也就理解了。

如下实例:
(1)以数组的第一个元素作为基准数,取出来,进行另存
在这里插入图片描述
(2)从区间的最右边找个比这个基准数小 的数,放到 它这个位置,如下图是找到了19.
在这里插入图片描述
放到原基准数的位置
在这里插入图片描述
(3)然后再在区间的最左边开始找比基准数大的元素找到了就放到R空的那个位置
如下图是找到了47
在这里插入图片描述
放到R空的位置
在这里插入图片描述

(4)如此这么循环,直到L和R相遇,把这个基准数填到相遇的位置
在这里插入图片描述
这样基准数的左边都比基准数小,基准数右边的都比基准数大。
如此这么递归,把所有区间递归完,即排完序了。

接下来我们看下代码:
代码实例中,我特地没在数组的第一个位置存储元素,特地用它来存储这个移出来,等待插入的基准数

#include<stdio.h>
#include<stdlib.h>
#define MAX 9
//单个记录的结构
typedef struct
{
	int key;
}SqNote;
//记录表的结构体
typedef struct
{
	SqNote r[MAX];
	int length;
}SqList;
int Partition(SqList *L,int low,int high)
{
	L->r[0]=L->r[low]; //下标为0的位置存放提取出来的基节点
	int pivotkey=L->r[low].key;
	//直到两指针相遇,程序结束
	while(low<high) 
	{
		//high指针左移,直到遇到比pivotkey值小的记录,指针停止移动
		while(low<high && L->r[high].key>=pivotkey)
		{
			high--;	
		} 
		//直接将high指向的小于支点的记录移动到low指针的位置
		L->r[low]=L->r[high];
		//low指针右移,直到遇到比pivotkey值大的记录,指针停止移动 
		while(low<high && L->r[low].key<=pivotkey)
		{
			low++;	
		} 
		//直接将low指向的大于支点的记录移动到high指针的位置
		L->r[high]=L->r[low]; 
	}
	//将支点添加到准确的位置
	L->r[low]=L->r[0];
	return low; 
}
void QSort(SqList *L,int low,int high)
{
	if(low<high)
	{
		//找到支点的位置
		int  pivotloc=Partition(L,low,high);
		//对支点左侧的子表进行排序
		QSort(L,low,pivotloc-1);
		//对支点右侧的子表 进行排序
		QSort(L,pivotloc+1,high); 
	}
}
void QuickSort(SqList *L)
{
	QSort(L,1,L->length);
}
int main()
{
	SqList *L=(SqList*)malloc(sizeof(SqList));
	L->length=8;
	L->r[1].key=49;
    L->r[2].key=38;
    L->r[3].key=65;
    L->r[4].key=97;
    L->r[5].key=76;
    L->r[6].key=13;
    L->r[7].key=27;
    L->r[8].key=49;
    QuickSort(L);
    for(int i=1;i<=L->length;i++)
    	printf("%d",L->r[i].key);
    return 0;
} 

快速排序算法的时间复杂度为O(nlogn),是所有时间复杂度相同的排序方法中性能最好的排序算法。

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

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

相关文章

Kubernetes_从Linux的cgroup配置到Kubernetes中的cgroup配置

系列文章目录 文章目录系列文章目录前言一、Linux层面的cgroup二、Kubernetes层面的cgroup driver2.1 kubelet和docker的Cgroup Driver不同导致kubelet开启失败2.1.1 命令2.1.2 演示总结前言 一、Linux层面的cgroup cgroup是控制组&#xff0c;用来控制进程对资源的分配&…

Cesium-数字仿真-你总要了解

Cesium&#xff08;专注于时空数据的实时可视化) cesium是一款三维地球开源框架&#xff08;可以多平台、跨平台使用&#xff09;cesium隶属于美国AGI公司&#xff08;Analytical Graphics Incorporation&#xff09;&#xff0c;美国通用公司宇航部的工程师创始开源 周边产…

微信小程序的优化方案之主包与分包的研究

什么是分包&#xff1f; 某些情况下&#xff0c;开发者需要将小程序划分成不同的子包&#xff0c;在构建时打包成不同的分包&#xff0c;用户在使用时按需进行加载。 在构建小程序分包项目时&#xff0c;构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的…

错误代码0xc0000001要怎么解决?如何修复错误

出现错误代码0xc0000001这个要怎么解决&#xff1f;其实这个的蓝屏问题还是非常的简单的&#xff0c;有多种方法可以实现 解决方法一 1、首先使用电脑系统自带的修复功能&#xff0c;首先长按开机键强制电脑关机。 注&#xff1a;如果有重要的资料请先提前备份好&#xff0c;…

【C++】C++11 ~ 包装器解析

&#x1f308;欢迎来到C专栏~~包装器解析 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&a…

Java 内存结构解密

程序计数器 物理上被称为寄存器&#xff0c;存取速度很快。 作用 记住下一条jvm指令的执行地址。 特点 线程私有&#xff0c;和线程一块出生。 不存在内存溢出。 虚拟机栈 每个线程运行时所需要的内存&#xff0c;称为虚拟机栈。 每个栈由多个栈帧组成&#xff0c;…

C/C++ 中的宏 (macros) 与宏展开的可视化显示

C/C 中的宏 (macros) 与宏展开的可视化显示1. Replacing text macros (替换文本宏) https://en.cppreference.com/w/cpp/preprocessor/replace https://www.codecademy.com/resources/docs/cpp/macros A macro is a label defined in the source code that is replaced by it…

dll修复工具哪个比较好?修复工具介绍

DLL&#xff08;动态链接库&#xff09;是Windows操作系统中非常重要的一部分&#xff0c;它们存储了各种软件应用程序所需的公共代码和数据。然而&#xff0c;随着时间的推移&#xff0c;电脑上的DLL文件可能会因为各种原因而损坏或丢失&#xff0c;导致系统出现错误。因此&am…

PyTorch自定义损失函数实现

在机器学习中&#xff0c;损失函数是衡量预测输出与实际输出之间差异的关键组成部分。 它在模型训练中起着至关重要的作用&#xff0c;因为它通过指示模型应该改进的方向来指导优化过程。 损失函数的选择取决于具体的任务和数据类型。 在本文中&#xff0c;我们将以用于手写数字…

VHDL语言基础-时序逻辑电路-概述

目录 时序逻辑电路-概述: 时序逻辑电路: 时序逻辑电路——有记忆功能: 时序电路的分类: 按照触发器的动作特点: 按照输出信号的特点: 同步时序逻辑电路: 异步时序逻辑电路: 时序逻辑电路-概述: 数字电路按其完成逻辑功能的不同特点&#xff0c;划分为组合逻辑电路和时序…

福利篇1——嵌入式软件行业与公司汇总

前言 汇总嵌入式软件行业与公司,供参考。 文章目录 前言一、嵌入式软件行业和公司汇总1、芯片行业代表性公司2、人工智能代表性公司1)智能驾驶方向代表性公司2)机器人方向代表性公司3、消费电子领域代表性公司4、传统电子电器领域代表性公司5、国企和军工领域代表性公司6、网…

嵌入式系统那些事——aarch64 backtrace嵌入式汇编实现

0 背景 在aarch64嵌入式应用开发中&#xff0c;经常会遇到段错误(segmentation fault)&#xff0c;但是通常情况下系统报错后直接退出&#xff0c;没有异常调用打印信息&#xff0c;定位出错原因十分困难。经确认&#xff0c;该问题是由于没有设置捕获段错误&#xff0c;并调用…

推荐3dMax三维设计十大插件

3dMax是一款功能非常强大的三维设计软件&#xff0c;但无论它的功能多么强大&#xff0c;也不可能包含所有三维方面的功能&#xff0c;这时候&#xff0c;第三方插件可以很好的弥补和增强3dMax的基本功能&#xff0c;下面就给大家介绍十款非常不错的3dMax插件。 森林包&#xf…

Unsupervised Question Answering 简单综述

Unsupervised Question Answering by Cloze Translation, ACL 2019 随机从文本中抽取noun phrases或者named entity作为答案将答案部分mask掉&#xff0c;生成cloze question利用无监督翻译&#xff0c;将cloze question转化为natural question 缺点&#xff1a; 直接利用原句…

Android 进阶——Framework核心 之Binder Native成员类详解(二)

文章大纲引言一、Native 家族核心成员关系图二、Native 家族核心成员源码概述1、IInterface1.1、DECLARE_META_INTERFACE 宏1.2、IMPLEMENT_META_INTERFACE(INTERFACE, NAME) 宏1.3、sp< IInterface > BnInterface< INTERFACE >::queryLocalInterface(const String…

微前端qiankun架构 (基于vue2实现)使用教程

工具使用版本 node --> 16vue/cli --> 5 创建文件 创建文件夹qiankun-test。 使用vue脚手架创建主应用main和子应用dev 主应用 安装 qiankun: yarn add qiankun 或者 npm i qiankun -S 使用qiankun&#xff1a; 在 utils 内创建 微应用文件夹 microApp,在该文件夹…

_Linux (线程池)

文章目录线程池概述&#xff1a;线程池示例&#xff1a;代码细节代码结果展示线程池概述&#xff1a; 一种线程使用模式。 线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务。这避…

Linux下文档类型转PDF的总结

我的环境 centos8 先说思路:先把字体上传到服务器,然后更新字体库 ,代码里面配置字体地址。 如果导出的还是乱码,要么没字体,要么检查代码里面的路径。 目录 1.上传windows字体到linux 2.建立索引信息,更新字体缓存

【基于ChatGPT+Python】快速打造前后端分离的OpenAI人工智能聊天机器人

&#x1f680; ChatGPT是最近很热门的AI智能聊天机器人 &#x1f680; 用途方面相比于普通的聊天AI更加的广泛&#xff0c;甚至可以帮助你改BUG&#xff0c;写代码&#xff01;&#xff01;&#xff01; &#x1f680; 下面是使用pythonChatGPTVue实现的在线聊天机器人&#xf…

shell脚本免交互与expect

目录 Here Document 定义 格式 注意 例子 统计行数 修改密码​编辑 expect 定义 基本命令 实验 免交互ssh主机 Here Document 定义 使用I/O重定向的方式将命令列表提供给交互式程序 格式 命令<< 标记....标记 注意 标记可以使用任意的合法字符&#xf…