前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >有关排序的算法

有关排序的算法

作者头像
用户11352420
发布2024-11-07 21:31:26
520
发布2024-11-07 21:31:26
举报
文章被收录于专栏:编程学习

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

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

选择法排序

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

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

代码如下:

代码语言:javascript
复制
//选择法排序
#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;
}

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

代码语言:javascript
复制
#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.

代码如下:

代码语言:javascript
复制
//冒泡排序
#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;
}

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

代码语言:javascript
复制
#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;
}

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

代码语言:javascript
复制
#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排序整型

代码语言:javascript
复制
//测试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);

代码语言:javascript
复制
#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排序结构体类型

代码语言:javascript
复制
//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进行详细讲解。

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

代码语言:javascript
复制
#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;
}

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 选择法排序
  • 冒泡法排序
  • qsort排序(快速排序)
    • qsort排序整型
      • qsort排序结构体类型
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档