C语言之冒泡算法排序数据及库函数qsort函数的使用及模拟实现

  1. C语言之冒泡算法排序数据及库函数qsort函数的使用及模拟实现

    冒泡算法实现数据排序


    文章目录

    • 冒泡算法排序整型数组
    • c语言库函数qsort的使用
    • 模拟实现qsort函数

    一、冒泡算法排序整型数据

1、冒泡算法实现排序,即相邻两个数据相比较,若前者大于后者则交换两数据(以升序为例)

2、对于一组数据从左到右完成一趟比较及交换,可以将最大的数据放在最右边(以升序为例)

3、有10个数据,则需要进行9趟比较及交换

4、对于每一趟,需要进行比较的此数依次减1,因为右边一部份数据已排好顺序,无需再比较

#include 

//将整型数据由大到小排序,排序使用的算法——冒泡算法,即相邻两数依次比较,若大则交换

void Bubble_sort(int arr[], int sz)
{
	int i = 0;
	int j = 0;
	int ret = 0;
	for (j = 0; j < sz - 1; j++)//控制趟数//注意sz个数排序,则需要sz-1趟完成排序,而j从0开始,到sz-1是进行了sz次,故用小于号,而不用小于等于
	{
		for (i = 0; i < sz - 1 - j; i++)//控制每趟比较次数//注意此处sz表示数组大小为9,而由于涉及i及i+1同时出现,故i最大是sz-2,而sz-1
		{
			if (arr[i] > arr[i + 1])
			{
				ret = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = ret;

			}
		}
	}
}

void print_result(int arr[],int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[] = {2,4,5,1,6,7,8,9,3 };
	int sz = sizeof(arr) / sizeof(arr[0]);//将数组作为实参传入函数,实际只传入了首元素地址,故需另外搭配数组元素个数
	Bubble_sort(arr, sz);
	print_result(arr, sz);
	return 0;
}
  1. 二、c语言库函数qsort的使用

    1.qsort函数简介

  1、qsort函数使用前应引入头文件

  2、参数介绍

void qsort (void* base, size_t num, size_t size,
            int (*compar)(const void*,const void*));

第一个参数是传入待排序数据的首地址;第二个参数是待排序数据的个数;第三个参数是一个数据所占字节数;第四个参数是函数指针,指向自己定义的比较函数,该函数返回类型为int型,两个参数均为const void*,传入两个待比较数据的地址,同时要注意函数内部逻辑,即要实现升序,则两数比较前者小于后者则返回-1,前者大于后者则返回1,二者相等则返回0.(ps:若要实现降序,则将自己定义的比较函数内部逻辑取反即可)

3、qsort函数可以实现对任意类型数据进行排序,如整型,结构体等,以下两例分别利用qsort函数实现整形数据的升序以及结构体数据按姓名升序排列


//使用qsort函数实现整型数据升序,若要实现降序,则自己设计的比较函数,逻辑取反即可
int Compare(const void* p1, const void* p2)
{
	if (*(int*)p1 < *(int*)p2) return -1;
	if (*(int*)p1 == *(int*)p2) return 0;
	if (*(int*)p1 > *(int*)p2) return 1;

}

void print_result(int arr[],int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
#include 
int main()
{
	int arr[] = { 2,4,3,1,5,9,7,8,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), Compare);
	print_result(arr, sz);

}
	


//qsort函数不仅速度快,且可以对任意类型数据进行排列
#include 
#include 
struct stu
{
	char name[20];
	int age;

};
//注意比较两个字符串,使用strcmp函数,参数是两个const char*类型指针
int Compare_name(const void* p1,const void* p2)
{
	if (strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name)<0) return -1;
	if (strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name) > 0) return 1;
	if (strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name)==0) return 0;

}

void print_result(struct stu arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d\n", arr[i].name,arr[i].age);
	}
}

int main()
{
	struct stu arr[] = { {"李明",20} ,{"张三",15}, {"胡图",14} };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), Compare_name);
	print_result(arr, sz);

}

  1. 三、模拟实现qsort函数(此处利用冒泡算法模拟实现qsort函数)

     

     1、算法的总体思路即利用两个循环变量分别控制趟数以及每趟比较对象的偏移,对相邻的两个数据比较,若不满足升序则交换

    2、由于事先不知道数据类型,故函数形参的指针应为无类型指针,且比较函数Compare的参数也应为无类型指针,应当注意无类型指针使用前应当强制类型转换为其他有类型指针

     3、而在进行比较时,要在未知数据类型的情况下进行数据的偏移,则利用字符指针以及一个数据的大小(即占据多少字节)实现偏移

    4、而在进行两个数据交换时,要在未知数据类型的情况下进行数据的交换,只能利用内存中最小单元一个字节一个字节地交换

  2. //利用冒泡算法,模拟实现qsort函数,虽qsort内部不是由冒泡算法实现的
    #include
    void Swap(void* p1, void* p2, int data_size);
    struct stu
    {
    		char name[20];
    		int age;
    	
    };
    
    void print_result(struct stu arr[], int sz)
    {
    	int i = 0;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%s %d\n", arr[i].name, arr[i].age);
    	}
    }
    
    void bubble_qsort(void* data, int sz, int data_size, int (*compare)(const void*, const void*))
    {
    	int i = 0;
    	int j = 0;
    	for (j = 0; j < sz - 1; j++)
    	{
    		for (i = 0; i < sz - 1 - j; i++)
    		{
    			if (compare((char*)data + i * data_size, (char*)data + (i + 1) * data_size) > 0)//由于该排序代码要适用于所有数据类型,所以要实现偏移一个数据的大小,要将无类型指针强转为char*,再利用形参中的一个数据大小data_size实现偏移
    			{
    				Swap((char*)data + i * data_size, (char*)data + (i + 1) * data_size,data_size);
    			}
    		}
    	}
    }
    
    void Swap(void* p1, void* p2,int data_size)
    {
    	int i = 0;
    	char ret = 0;//注意此处不用char* ret=NULL因为后续代码涉及对ret进行访问修改值,除非使用前改变空指针指向否则不可直接访问修改
    	for (i = 0; i < data_size; i++)
    	{
    		ret = *((char*)p1 + i); 
    		*((char*)p1 + i) = *((char*)p2 + i);//在未知数据类型的情况下,要进行数据的交换,只能利用内存中最小单元一个字节一个字节地交换;而在未知数据类型的情况下,要进行数据的偏移,则利用字符指针以及一个数据的大小(即占据多少字节)实现偏移
    		*((char*)p2 + i) = ret;
    	}
    }
    
    int Compare_name(const void* p1,const void* p2)
    {
    	if (strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name)<0) return -1;
    	if (strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name) > 0) return 1;
    	if (strcmp(((struct stu*)p1)->name, ((struct stu*)p2)->name)==0) return 0;
    
    }
    
    int main()
    {
    		struct stu arr[] = { {"李明",20} ,{"张三",15}, {"胡图",14} };
    		int sz = sizeof(arr) / sizeof(arr[0]);
    		bubble_qsort(arr, sz, sizeof(arr[0]), Compare_name);
    		print_result(arr, sz);
    		return 0;
    }

你可能感兴趣的:(算法,数据结构,排序算法,c语言)