冒泡排序那些事

冒泡排序:它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误,就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换的,即该数列排序完成。这个算法的名字由来是因为越大的元素经过交换慢慢“浮到”数列的顶端,故称冒泡排序。

算法原理
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素做同样的工作,从开始的第一对,到结尾的最后一对。在这一点,最后的元素应该是最大的数。
3.针对所有元素重复以上的步骤,除了最后一个。
4.持续每一对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

简单的冒泡排序:

 
 
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0; 
	int j = 0;
	int tmp = 0;
	for (i = 0; i < sz - 1; i++)
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	
	int arr[10] = { 1, 4, 6, 7, 8, 9, 5, 3, 10, 2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	print_arr(arr, sz);
	return 0;
}


在这里有两个要点:
1.使用嵌套的for循环来控制
2.如果满足条件进行交换

对于这种方法,会效率比较低下,如果后面的数据已经排好序,但是程序还是会进行判断,所以,我们可以实现优化。
优化方法:
 
 
#include<stdio.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	int j = 0;
	int tmp = 0;
	int flag = 1;
	for (i = 0; i < sz - 1 && flag; i++)
	{
		flag = 0;  //设置一个标志变量,如果数据顺序没有变化,那么结束程序
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				flag = 1;
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}
void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[10] = { 1, 4, 2, 3, 5, 6, 7, 8, 9, 10 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	bubble_sort(arr, sz);
	print_arr(arr, sz);
	return 0;
}


使用指针的方法:

 
 
 
 
void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
void bubble_sort(int * arr, int sz)
{
	int * start = arr;
	int * end = arr + sz - 1;
	int tmp;
	for (start = arr; start < end; end--)
	{
		//使用一个临时指针来实现相邻元素的交换
		int * cur = start;
		for (cur = start; cur < end; cur++)
		{
			if (*cur > *(cur + 1))
			{
				tmp = *cur;
				*cur = *(cur + 1);
				*(cur + 1) = tmp;
			}
		}
	}
}
int main()
{
	
	int arr[10] = { 1, 4, 6, 7, 8, 9, 5, 3, 10, 2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	print_arr(arr, sz);
	return 0;
}


这里的解释图如下:

 
经过一趟循环之后,实现end--,而且cur要回到起始的地址。

扫描二维码关注公众号,回复: 1069384 查看本文章
模拟实现一个通用的冒泡排序:
在这里,我们通过学习qsort(快速排序)来实现。

qsort利用两个函数:
1.显示函数:来接收各种类型的数据,其中比较函数的地址是此函数的一个参数
2.比较函数:得自己来实现各种比较函数。

void qsort(void *base, size_t num, size_t width,  int(__cdecl *compare)(const void *elem1, const void *elem2));
参数解释:

base:目标数组的起始地址
num:数组中元素的个数
width:元素大小
函数指针:函数的参数为void *,使得数组和字符串也能被使用。

 
 
#include<stdio.h>
#include<assert.h>
int cmp_int(const void * e1, const void * e2)  //强制类型转换并解引用可以得到两个元素
{
	return *(int *)e1 - *(int *)e2 ;
}
void print_arr(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
void Swap(char * buf1, char * buf2, int width)
{
	int i = 0;
	char tmp;
	assert(buf1&&buf2);
	for (i = 0; i < width; i++)
	{
		tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;  //一个字节一个字节的交换
		buf2++;
	}
}
void bubble_sort(void * base, int sz, int width, int(*cmp)(void * e1, void * e2))
{
	int i = 0;
	int j = 0;
	assert(base&&cmp);
	for (i = 0; i < sz - 1; i++) 
	{
		for (j = 0; j < sz - i - 1; j++)
		{
			//要拿到两个元素的地址
			if (cmp(((char *)base + width*j), (char *)base + width*(j+1))>0)
			{
				//交换
				Swap(((char *)base + width*j), (char *)base + width*(j + 1), width);
				
			}
		}
	}
}
int main()
{
	int arr[10] = { 1, 2, 4, 7, 8, 0, 9, 5, 6, 3 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
	print_arr(arr, sz);
	return 0;
}

下面是运算结果图:

猜你喜欢

转载自blog.csdn.net/miqingzhiwen/article/details/80157882