有关排序的算法

news2024/11/19 19:44:49

目录

选择法排序

冒泡法排序

qsort排序(快速排序)

qsort排序整型

qsort排序结构体类型


排序是我们日常生活中比较常见的问题,这里我们来说叨几个排序的算法。

比如有一个一维数组 arr[8] ={2,5,3,1,7,6,4,8},我们想要把它排成升序,我们通过下面这几种不同的方式来进行排序!

选择法排序

这一种排序方式,首先第一轮认为第一个元素是最小的,把它的下标用 flag 记下来,不断与后面的元素进行比较,如果后面的元素有比它小的,就把 flag 改成比它小的元素下标,直到把整个数组下标遍历完,如果flag不等于最开始的下标就进行交换,这样就可以得到最小的那个数在第一位,依此类推,第二轮找到第二小的数字放在第二位,第三轮找到第三小的数字放在第三位……

当第七轮的时候已经找到了找到第七小的数字放在第七位,显然最后一位是最大的数字,所以一共进行七次就好了!

代码如下:

//选择法排序
#include<stdio.h>
int main()
{
	int arr[8] = { 2,5,3,1,7,6,4,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int j = 0;
	int flag = 0;
	printf("排序前:\n");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	for (i = 0; i < sz - 1; i++)
	{
		flag = i;
		for (j = i + 1; j < sz; j++)
		{
			if (arr[j] < arr[flag])
				flag = j;
			//如果后面的元素比flag为坐标的元素小,就把flag改成较小元素的坐标
		}
		if (flag != i)
		{
			int temp = arr[i];
			arr[i] = arr[flag];
			arr[flag] = temp
		}
	}
	printf("\n排序后:\n");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}


当然,在学习了指针的基础上,我们可以把排序代码分装成函数的形式


#include<stdio.h>
void Print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}
void Choose_sort(int* arr, int sz)
{
	int flag = 0;
	for (int i = 0; i < sz - 1; i++)
	{
		flag = i;
		for (int j = i + 1; j < sz; j++)
		{
			if (arr[j] < arr[flag])
				flag = j;
		}
		if (flag != i)
		{
			int temp = arr[i];
			arr[i] = arr[flag];
			arr[flag] = temp;
		}
	}
}
int main()
{
	int arr[8] = { 2,5,3,1,7,6,4,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	Choose_sort(arr, sz);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}



冒泡法排序

这个与选择法排序有点相似,它的核⼼思想是两两相邻的元素进⾏⽐较,如果后面的元素比前面小,那么就立刻进行交换,第一轮最终会把最大的元素放在最后一位,依次往后面推进,在第七轮的时候,第二小的就在第二位了,所以只需要7趟就好了,每一趟就会找到一个元素放在相应的位置,所以每一趟比较的数组元素也会依次减1.

代码如下:


//冒泡排序
#include<stdio.h>
int main()
{
	int arr[8] = { 2,5,3,1,7,6,4,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	int j = 0;
	printf("排序前:\n");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	for (i = 0; i < sz - 1; i++)
	{
		//i代表趟数
		for (j = 0 ; j < sz - 1 - i; j++)
		{
			//访问数组元素两两比较
			if ( arr[j+1]<arr[j])
			{
				int temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}		
		}	
	}
	printf("\n排序后:\n");
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

我们也可以把排序代码分装成函数的形式:

#include<stdio.h>
void Print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}
void Bubble_sort(int* arr, int sz)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (*(arr+j+1) < *(arr+j))
			{
				int temp = *(arr + j + 1);
				*(arr + j + 1) = *(arr + j);
				*(arr + j) = temp;
			}
			/*if (arr[j + 1] < arr[j])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}*/
		}
	}
}
int main()
{
	int arr[8] = { 2,5,3,1,7,6,4,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	Bubble_sort(arr, sz);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}



我们来考虑一个问题,如果一个数组元素已经有序了,事实上,我们可以不用再进行排序了,那么应该怎么优化这个排序代码呢?

#include<stdio.h>
void Print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}
void Bubble_sort(int* arr, int sz)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;//最开始就假设有序
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (*(arr + j + 1) < *(arr + j))
			{
				flag = 0;//进来就说明还没有有序,让flag=0
				int temp = *(arr + j + 1);
				*(arr + j + 1) = *(arr + j);
				*(arr + j) = temp;
			}
		}
		if (flag == 1)//一趟下来flag=1,说明没有机会让flag=0,已经有序
		{
			printf("\n已经有序!\n");
			break;
		}
	}
}
int main()
{
	int arr[8] = { 1,2,3,4,5,6,7,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	Bubble_sort(arr, sz);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}



这里我们就可以使用一个flag来进行标记,flag=1,就说明已经有序,跳出循环,当一个数组已经已经有序或者接近有序的时候就可以减少运算次数

qsort排序(快速排序)

想要使用qsort函数呢?我们就需要先对这个函数进行一定的了解。

打开cplusplus网站,我们可以找到相关信息:

qsort(quick sort)事实上是C语言中的一个库函数,底层使用的是快速排序的思想,

并且对任意类型数据都可以进行排序

我们来看看每一个参数

base:指向需要排序数组的首元素地址(指针)

num:base指向数组中的元素个数

size:bas指向的数组中一个元素的字节大小

compar:函数指针,传递函数的地址

compar应该设计成下面这个样子,同时它的返回值也有要求

 
int compar (const void* p1, const void* p2);

当p1指向的元素小于p2指向的元素时,返回一个小于0的数字

当p1指向的元素等于p2指向的元素时,返回0

当p1指向的元素大于p2指向的元素时,返回一个大于0的数字

qsort排序整型

//测试qsort排序整型

#include<stdio.h>
#include<stdlib.h>
void Print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}
int cmp_int(const void* p1, const void* p2)
{
	if (*(int*)p1 > *(int*)p2)
	{
		return 1;
	}
	//知道比较整型,强制类型转换为整型,然后解引用
	else if (*(int*)p1 < *(int*)p2)
	{
		return -1;
	}
	else
	{
		return 0;
	}
}
int main()
{
	int arr[8] = { 2,5,3,1,7,6,4,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}

我们可以看见qsort进行了很好的排序,当然这里因为它的规则是

当p1指向的元素小于p2指向的元素时,返回一个小于0的数字

当p1指向的元素等于p2指向的元素时,返回0

当p1指向的元素大于p2指向的元素时,返回一个大于0的数字

所以我们可以把return语句直接写成:

return *((int*)p1) - *((int*)p2);

#include<stdio.h>
#include<stdlib.h>
void Print_arr(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
}
int cmp_int(const void* p1, const void* p2)
{
	//return *((int*)p1) - *((int*)p2);//默认升序
	//知道比较整型,强制类型转换为整型,然后解引用
	return *((int*)p2) - *((int*)p1); // 降序
}
int main()
{
	int arr[8] = { 2,5,3,1,7,6,4,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}


使用qsort默认是升序,如果想要降序,交换p1,p2的位置就可以了,比如上面的代码就可以实现降序。

qsort排序结构体类型

//qsort排序结构体类型
#include<stdio.h>
#include<stdlib.h>//qsort头文件
#include<string.h>//strcmp头文件
struct Student
{
	char name[20];
	int age;
};
void Print_arr(struct Student* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%s %d\n", arr[i].name, arr[i].age);
}
int cmp_student_by_name(const void* p1, const void* p2)
{
	return strcmp(((struct Student*)p1)->name, ((struct Student*)p2)->name);
	//strcmp比较字符串,比较第一个不同字符的ASCII值
}
int main()
{
	struct Student arr[3] = { {"lihua",18},{"balla",56},{"guna",23} };
	//结构体数组
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), cmp_student_by_name);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}

这里依然是比较的时候强制类型转换为结构体类型,使用了结构体访问操作符【->】特殊的是比较字符串需要使用strcmp函数,不清楚的可以看看【数组的使用】那一篇博客对strcmp进行详细讲解。

我们也可以通过年龄来比较,代码如下:

#include<stdio.h>
#include<stdlib.h>//qsort头文件
//#include<string.h>//strcmp头文件
struct Student
{
	char name[20];
	int age;
};
void Print_arr(struct Student* arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%s %d\n", arr[i].name, arr[i].age);
}
int cmp_student_by_age(const void* p1, const void* p2)
{
	return (((struct Student*)p1)->age - ((struct Student*)p2)->age);
}
int main()
{
	struct Student arr[3] = { {"lihua",18},{"balla",56},{"guna",23} };
	//结构体数组
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:\n");
	Print_arr(arr, sz);
	qsort(arr, sz, sizeof(arr[0]), cmp_student_by_age);
	printf("\n排序后:\n");
	Print_arr(arr, sz);
	return 0;
}


当然排序算法永远不止于此,还有更多的内容等待着我们去发现,去应用。

加油吧!未来的顶尖程序员们!!!!

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

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

相关文章

苹果将推出全新AI培训课程;生成式AI手机市场将迎来爆发式增长

&#x1f989; AI新闻 &#x1f680; 苹果将推出全新AI培训课程 摘要&#xff1a;IT之家消息&#xff0c;苹果宣布&#xff0c;今年秋季将在6个国家的18所开发者学院推出AI培训课程&#xff0c;目标群体为学生、导师和校友。课程涵盖机器学习模型的构建及部署&#xff0c;Cor…

姜萍的启示:分数不是唯一,天赋引领专业选择超越名校

你好&#xff0c;我是三桥君。 24年高考帷幕落下&#xff0c;一场新的思考与选择悄然来临。 对于每一位高考考生&#xff0c;学校和专业都是开启大学新生活的两个前置必选项。 在这关键时刻&#xff0c;全网媒体却被一则关于“一名17岁中专女学生姜萍在全球数学竞赛获得第12名”…

数字孪生涉及到的9大技术栈,都是难啃骨头呀。

数字孪生涉及到多个技术栈&#xff0c;包括但不限于以下几个方面&#xff1a; 数据采集和传感器技术&#xff1a; 数字孪生需要实时获取物理世界的数据&#xff0c;因此需要使用各种传感器技术&#xff08;如温度传感器、压力传感器、运动传感器等&#xff09;来采集数据&…

排序(3)【归并排序】【计数排序】【排序算法度及其稳定性分析】

一.归并排序 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有…

C++ 66 之 类模版

#include <iostream> #include <string> using namespace std;// 习惯性 < >中 类模板用class 普通的函数模板就用typename // template<class NAMETYPE, class AGETYPE> template<class NAMETYPE, class AGETYPE int> // 可以设置默认的类型值…

集团门户网站的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;集团文化管理&#xff0c;基础数据管理&#xff0c;公告通知管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;论坛&#xff0…

收银系统源码-千呼新零售2.0【线下促销】

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货等连锁店使用。 详细介绍请查看下…

在LangChain中,LLM(大型语言模型)和LLM Chain的区别是什么?

简单来说&#xff0c;LLM是一个大型语言模型&#xff0c;而LLM Chain是由多个LLM或其他组件组成的链式结构&#xff0c;用于在LangChain中构建复杂的自然语言处理流程。 Direct LLM Interface: 直接大型语言模型&#xff08;LLM&#xff09;接口&#xff1a; llm Open…

【NOI-题解】1234. 任意输入一正整数N,要求把它拆成质因子的乘积。1446. 人口增长问题

文章目录 一、前言二、问题问题&#xff1a;1234. 任意输入一正整数N&#xff0c;要求把它拆成质因子的乘积。问题&#xff1a;1446. 人口增长问题 三、感谢 一、前言 本章节主要对循环应用的题目进行讲解&#xff0c;包括《1234. 任意输入一正整数N&#xff0c;要求把它拆成质…

防止员工离职导致数据泄露,员工离职后把文件带出公司

中科数安的电脑文件资料透明加密防泄密系统确实能够在一定程度上防止员工离职导致的数据泄露。以下是具体的分析&#xff1a; www.weaem.com 访问控制与权限管理&#xff1a;系统实施了严格的权限管理制度&#xff0c;对核心文件和数据资源进行细致的访问权限划分。这意味着&am…

【数据结构与算法】稀疏矩阵(三元组,十字链表存储)详解

给出稀疏矩阵的节省内存的存贮结构并写出相应的输入、输出算法。 稀疏矩阵是一个大部分元素为0的矩阵。为了节省内存&#xff0c;我们可以只存储非零元素。一种常见的存储结构是三元组&#xff0c;每个三元组包含一个非零元素的行索引、列索引和值。 #include <stdio.h>…

BC-Linux 8.6最小化安装的服务器启用GNOME图形化界面

本文记录了BC-Linux 8.6最小化安装的服务器如何启用GNOME图形化界面的过程。 一、服务器环境 1、系统版本 [rootlocalhost ~]# cat /etc/os-release NAME"BigCloud Enterprise Linux" VERSION"8.6 (Core)" ID"bclinux" ID_LIKE"rhel fe…

基于STM32和人工智能的智能小车系统

目录 引言环境准备智能小车系统基础代码实现&#xff1a;实现智能小车系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统4.4 用户界面与数据可视化应用场景&#xff1a;智能小车管理与优化问题解决方案与优化收尾与总结 1. 引言 随着机器人技术的发展&#xff0c;智能小…

Android断点续传原理及实现

常见两种网络请求方式 一、 HttpURLConnection HttpURLConnection的setRequestProperty()方法&#xff0c;对我们要读取的字节部分进行控制&#xff0c;比如: 1.Range0-100代表只读取前100个字节。 2.Range100-500代表读取从第100个字节开始&#xff0c;读到第500个字节为止。…

教你如何安装 IntelliJ IDEA

安装 IntelliJ IDEA 的步骤通常如下&#xff0c;这里提供的是基于 Windows 系统的安装指南。 下载 IntelliJ IDEA 1. 访问 JetBrains 官方网站&#xff1a;[https://www.jetbrains.com/idea/download/](Download IntelliJ IDEA – The Leading Java and Kotlin IDE) 2. 选择适…

让AI代替我写代码???——Codeium安装及使用

序 不知不觉又到了期末大作业的时间了&#xff0c;面对老师布置的超繁琐代码项目&#xff0c;竟一时有些发怵&#xff0c;不知道从何下手才好…… 但是&#xff0c;懒惰如张同学的我怎么能拘泥于老老实实完成这些毫无技术可言的作业呢&#xff1f; 于是乎&#xff0c;我便寻…

【YOLOv9改进[注意力]】在YOLOv9中使用注意力CascadedGroupAttention(2023)的实践 + 含全部代码和详细修改方式

本文将进行在YOLOv9中使用注意力CascadedGroupAttention的实践,助力YOLOv9目标检测效果的实践,文中含全部代码、详细修改方式。助您轻松理解改进的方法。 改进前和改进后的参数对比: 目录 一 CascadedGroupAttention 二 在YOLOv9中使用注意力CascadedGroupAttention的实…

【操作系统】操作系统实验04-文件系统扩展

题目要求&#xff1a; 对【程序5_9】进行扩展&#xff0c;要求参数为目录名&#xff0c;且其下至少有三层目录&#xff0c;分别用深度遍历及广度遍历两种方法对此目录进行遍历&#xff0c;输出此目录下所有文件的大小及修改时间。 1. 程序代码&#xff08;注意程序格式&#…

SYD88xx使代码在RAM内存中执行/运行

SYD88xx使代码在RAM中执行 SYD8811/8810默认都是cache模式的&#xff0c;但是在代码首次运行的时候&#xff0c;需要将代码从flash搬到cache中执行&#xff0c;这样第一次的代码执行可能会比较慢&#xff0c;这里提供一个将需要提速的代码放到RAM中执行的方法。 对于SYD8811…

【操作系统】操作系统实验03-页面置换算法

题目要求&#xff1a; 先读懂实验文档中的两个页面置换算法&#xff0c;参考文档中程序&#xff0c;实现以下要求&#xff1a; 假设某个进程P有6个页面&#xff0c;进程访问页的顺序自拟&#xff08;不少于20个&#xff09;&#xff0c;在内存中分配给该进程4个页面&#xff…