数据结构-C语言-排序(4)

news2024/11/24 12:07:59

代码位置:   

         test-c-2024: 对C语言习题代码的练习 (gitee.com)

一、前言:

1.1-排序定义:

        排序就是将一组杂乱无章的数据按照一定的规律(升序或降序)组织起来。(注:我们这里的排序采用的都为升序)

1.2-排序分类:

常见的排序算法:

  • 插入排序
    a. 直接插入排序
    b. 希尔排序

  • 选择排序
    a. 选择排序
    b. 堆排序
  • 交换排序
    a. 冒泡排序
    b. 快速排序
  • 归并排序
    a. 归并排序
  • 非比较排序
    a.计数排序
    b.基数排序

1.3-算法比较:

1.4-目的:

        今天,我们这里要实现的是归并排序、计数排序

二、归并排序-递归:

2.1-定义:

        归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

2.2-思路:

归并排序两个基本过程:

        1、分:将原数组分割成两个平分子数组的过程。

        2、治:将分割后的数组两两结合成一个有序的数组的过程。

归并排序两个基本操作:

  1. 将待排序的线性表不断地切分成若干个子表,直到每个子表只包含一个元素,这时,可以认为只包含一个元素的子表是有序表。
  2. 将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表。

2.3-过程图:

2.4-代码实现:

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

	int mid = (begin + end) / 2;
	//子区间递归
	_MagerSort(a, begin, mid, tem);
	_MagerSort(a, mid+1, end, tem);

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

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

	while (begin2 <= end2)
	{
		tem[i++] = a[begin2++];
	}
	memcpy(a + begin, tem + begin, sizeof(int) * (end - begin + 1));
}

//递归实现
void MagerSort(int* a, int n)				//归并排序---时间复杂度(O(N*logN))
{
	int* tem = (int*)malloc(sizeof(int) * n);
	if (tem == NULL)
	{
		perror("malloc MagerSort");
		return;
	}
	_MagerSort(a, 0, n - 1, tem);


	free(tem);
}

2.5-效果图:

三、归并排序-非递归:

3.1-定义:

        归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

3.2-思路:

        我们知道,递归实现的缺点就是会一直调用栈,而栈内存往往是很小的,如果调用次数过多就会出现栈溢出的现象。所以,我们尝试着用循环的办法去实现归并排序。

        我们可以通过间距值gap=1来实现将数组分割若干个只含一个数的子数组的操作,然后通过改变gap的值来实现两两合并的操作。

        注意:在循环过程中我们需要考虑是否有越界的问题,如果有的话我们可以通过改变begin和end的值的方式来调整范围,修正路线。

        拷贝时我们有两种拷贝方式:一种是全部拷贝(梭哈),另一种是部分拷贝。

3.3-过程图:

3.4-代码实现:


//非递归实现
//全部拷贝(梭哈)
void MergeSortNonR1(int* a, int n)		//归并排序---时间复杂度(O(N*logN))
{
	int* tem = (int*)malloc(sizeof(int) * n);
	if (tem == NULL)
	{
		perror("malloc fail\n");
		return;
	}

	
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i+=2*gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			//修正路线
			if (end1 >= n)
			{
				end1 = n-1;
				begin2 = n;
				end2 = n-1;
			}
			else if (begin2 >= n)
			{
				begin2 = n;
				end2 = n-1;
			}
			else if (end2 >= n)
			{
				end2 = n-1;
			}
			//归并
			int j = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] >= a[begin2])
				{
					tem[j++] = a[begin2++];
				}
				else
				{
					tem[j++] = a[begin1++];
				}
			}
			while (begin1 <= end1)
			{
				tem[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tem[j++] = a[begin2++];
			}	
			
		}
		memcpy(a, tem, sizeof(int) * n);
		gap *= 2;
	}

	free(tem);
}

//部份拷贝
void MergeSortNonR2(int* a, int n)		//归并排序---时间复杂度(O(N*logN))
{
	int* tem = (int*)malloc(sizeof(int) * n);
	if (tem == NULL)
	{
		perror("malloc fail\n");
		return;
	}


	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			//修正路线
			if (end1 >= n)
			{
				break;
			}
			else if (begin2 >= n)
			{
				break;
			}
			else if (end2 >= n)
			{
				end2 = n - 1;
			}
			//归并
			int j = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] >= a[begin2])
				{
					tem[j++] = a[begin2++];
				}
				else
				{
					tem[j++] = a[begin1++];
				}
			}
			while (begin1 <= end1)
			{
				tem[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tem[j++] = a[begin2++];
			}
			memcpy(a+i, tem+i, sizeof(int) * (end2 - i + 1));
		}
		
		gap *= 2;
	}

	free(tem);
}

3.5-效果图:

四、计数排序:

4.1-定义:

        计数排序是一种非比较排序算法。 它通过计算每个唯一元素的出现次数对数组进行排序。 它对唯一元素的计数进行部分哈希处理,然后执行计算以找到最终排序数组中每个元素的索引。 它是一个相当快的算法,但不适合大型数据集。 它作为基数排序中的一个子程序使用。

4.2-思路:

        1.开辟计数数组:如果数据为:(100,102,106,110,107)的话这里从0开始开辟的话就会开辟一个长度111个的数组其中有100个是浪费的,这样的话如果数据过大的话这个排序的效率就会非常的低。所以,这里我们数组长度的开辟采用最大值-最小值的方式,这样就避免了上述情况。

        2.出计数数组:出数组时我们是从计数数组的第一个下标中统计的个数依次往后出,出数组时我们需要下标加上最小值min,这样就实现排序啦!

4.3-过程图:

4.4-代码实现:


// 时间复杂度:O(N+range)
// 空间复杂度:O(range)
void CountSort(int* a, int n)					// 计数排序
{
	int max = a[0];
	int min = a[0];
	for (int i = 1; i < n; i++)
	{
		if (a[i] > max)
		{
			max = a[i];
		}
		if (a[i] < min)
		{
			min = a[i];
		}
	}
	int range = max - min+1;
	int* tem = (int*)malloc(sizeof(int) * range);
	if (tem == NULL)
	{
		perror("malloc");
		return;
	}
	//开辟的数组初始化为0
	for (int i = 0; i < range; i++)
	{
		tem[i] = 0;
	}
	for (int i = 0; i < n; i++)
	{

		int j = a[i] - min;
		tem[j]++;
	}
	int m = 0;
	for (int i = 0; i < range; i++)
	{
		while(tem[i]>0)
		{
			if (tem[i] != 0)
			{
				a[m++] = i + min;
				tem[i]--;
			}
		}
	}
}

4.5-效果图:

五、结语:

        上述内容,即是我个人对数据结构排序中归并排序、计数排序的个人见解以及自我实现。若有大佬发现哪里有问题可以私信或评论指教一下我这个小萌新。非常感谢各位uu们的点赞,关注,收藏,我会更加努力的学习编程语言,还望各位多多关照,让我们一起进步吧!

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

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

相关文章

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)

回溯算法今天这几个题目做过&#xff0c;晚上有面试&#xff0c;今天水一水。 第一题&#xff1a;Leetcode77. 组合 题目描述 解题思路 从题目示例来看&#xff0c;k个数是不能重合的&#xff0c;但是题目没有明确说明这一点。 使用回溯算法解决此问题&#xff0c;利用树形…

设计模式-结构型-09-外观模式

文章目录 1、影院管理项目2、外观模式基本介绍4、MyBatis 框架源码分析5、外观模式总结 1、影院管理项目 组建一个家庭影院&#xff1a; DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机&#xff0c;要求完成使用家庭影院的功能&#xff0c;其过程为&#xff1a; 直接用…

推荐一个酷炫高逼格的服务器探针的监控工具,免费开源(附源码)

背景 作为一名攻城狮&#xff0c;面对各种服务器内存飙高、CPU猛增、磁盘打满等等服务器问题&#xff0c;可谓是伤透了我们的心。 不仅要开发&#xff0c;还要处理这些问题&#xff0c;大把的时间浪费了&#xff0c;这时候一个好的全面的监控工具尤为重要了。 所以&#xff…

Spring AI (三) 提示词对象Prompt

3.提示词对象Prompt 3.1.Prompt Prompt类的作用是创建结构化提示词, 实现了ModelRequest<List<Message>>接口 Prompt(String contents)&#xff1a;创建一个包含指定内容的Prompt对象。 Prompt(String contents, ChatOptions modelOptions)&#xff1a;创建一个…

Github 2024-07-26 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-26统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9HTML项目1TypeScript项目1非开发语言项目1JavaGuide - Java 程序员学习和面试指南 创建周期:2118 天开发语言:Java协议类型:Apache…

【C++】初识C++基础篇·一(命名空间,函数重载,缺省参数,引用);

文章目录 前言1.输入与输出输出输入cin和scanf的对比 2.命名空间2.1namespace存在的意义2.2namespace的使用3.缺省参数4.函数重载重载函数的调用规则 5.引用 前言 我们先通过一段简单的代码来拉开C的序幕&#xff1b; //text.cpp #include<iostream> #include<stdio…

C++知识点总结:3.C++引用(自用)

C引用 1. 引用定义2. 引用的本质3. 引用和指针的不同之处补充指针常量和常量指针 4. 引用不能指代临时变量5. const引用&#xff08;常引用&#xff09;可以绑定临时数据6. const引用与转换类型 引用&#xff1a; [1]C语言中文网 [2]偶尔e网事,【C基础之二】常量指针和指针常量…

学习记录:ESP32控制舵机 FREERTOS BLE

控制舵机 PWM信号 PWM信号是一种周期性变化的方波信号&#xff0c;它有两个关键参数&#xff1a; 周期&#xff08;Period&#xff09;&#xff1a;一个完整的PWM信号的时间长度&#xff0c;通常用秒&#xff08;s&#xff09;或毫秒&#xff08;ms&#xff09;表示。占空比…

MQ消息队列+Lua 脚本实现异步处理下单流程

具体实现和代码可参考我以前做过的笔记&#xff1a;《黑马点评》异步秒杀优化|消息队列 回顾一下下单流程&#xff1a; 用户发起请求 会先请求Nginx,Nginx反向代理到Tomcat&#xff0c;而Tomcat中的程序&#xff0c;会进行串行工作&#xff0c; 分为以下几个操作&#xff1…

昇思25天学习打卡营第25天|基于 MindSpore 实现 BERT 对话情绪识别

基于 MindSpore 实现 BERT 对话情绪识别 模型概述 BERT&#xff08;双向编码器表征量&#xff09;是Google于2018年发布的一种先进语言模型&#xff0c;基于Transformer架构&#xff0c;具备双向上下文理解功能。BERT的预训练方法创新性地结合了两种任务&#xff1a; Masked …

高级网页爬虫开发:Scrapy和BeautifulSoup的深度整合

引言 在互联网时代&#xff0c;数据的价值日益凸显。网页爬虫作为一种自动化获取网页内容的工具&#xff0c;广泛应用于数据挖掘、市场分析、内容聚合等领域。Scrapy是一个强大的网页爬虫框架&#xff0c;而BeautifulSoup则是一个灵活的HTML和XML文档解析库。本文将探讨如何将…

凸优化笔记-基本概念

原文 文章目录 最小二乘问题 仿射affine hullaffine dimension 凸集锥集超平面和半空间单纯形整半定锥保凸性的操作透视函数 凸函数的条件1阶判定条件2阶判定条件 Epigraph 外图 m i n i m i z e f 0 ( x ) minimize\ \ \ f_0(x) minimize f0​(x) s u b j e c t t o f i ( …

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」

Python 爬虫入门&#xff08;一&#xff09;&#xff1a;从零开始学爬虫 「详细介绍」 前言1.爬虫概念1.1 什么是爬虫&#xff1f;1.2 爬虫的工作原理 2. HTTP 简述2.1 什么是 HTTP&#xff1f;2.2 HTTP 请求2.3 HTTP 响应2.4 常见的 HTTP 方法 3. 网页的组成3.1 HTML3.1.1 HTM…

Debug下载与安装(Windows11)

前言 在安装配置前我们先下载一下我们需要用的文件 下载debug 百度网盘下载 下载DOSBox DOSBox 两个文件下载好后我们就开始安装和配置了 第一步&#xff1a;安装DOSBox 第二步&#xff1a;安装好后找到安装路径找到Options.bat文件并打开 第三步&#xff1a;在文件最下…

图片变色,背景方向渐变web

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>图片变色</title> <script src"03.JS\3.8JS案例加强\JQuery.js"></script> <style> .image-filter…

nvm 安装和遇到的问题

环境 win 11 安装 下载安装包 访问 https://github.com/coreybutler/nvm-windows/releases 选择需要的版本继续下载安装基本是可以下一步下一步的啦&#x1f92d; 安装 node 我这里需要16.x.x的node&#xff0c;执行以下命令 nvm install 16使用 node nvm use 16问题 …

苹果CMS V10萌芽采集插件Pro v10.7.3

苹果CMS V10萌芽采集插件Pro v10.7.3 插件下载:萌芽采集插件Pro v10.7.3.zip 使用说明: 将addons文件和static文件放到你苹果cms程序的根目录并覆盖&#xff0c; 在登录后台在应用-应用市场启用。http://你的域名/admin.php/admin/mycj/union.html

卷积的意义及其派生(一)

1.卷积的意义 1.1从LTI的角度看 卷积最开始其实是信号处理中用来描述线性移不变系统Linear time-invariant systems的。线性&#xff0c;表明可以叠加&#xff0c;信号可以拆分成脉冲的响应&#xff1b;时不变&#xff0c;指信号不随着时间的迁移改变&#xff0c;意味着能量守…

计算机网络(Wrong Question)

一、计算机网络体系结构 1.1 计算机网络概述 D 注&#xff1a;计算机的三大主要功能是数据通信、资源共享、分布式处理。&#xff08;负载均衡、提高可靠性&#xff09; 注&#xff1a;几段链路就是几段流水。 C 注&#xff1a;记住一个基本计算公式&#xff1a;若n个分组&a…

C语言程序设计(二)

四.找素数 素数&#xff1a;除了1和它本身不再有其他因数的自然数。换句话说&#xff1a;一个大于1的自然数 &#xff0c;如果只能被1和它本身整除&#xff0c;那就是素数&#xff08;质数&#xff09;。 在打印中遇到的问题就是&#xff0c;知道怎么写却总是运行不起来。主要…