各种排序算法(1)冒泡排序 选择排序 快速排序

1. 冒泡排序

1.1 名字由来:

算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序排列),
就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

1.2 冒泡思想

重复地遍历过要排序的数列,依次比较两个相邻的元素,如果他们的顺序错误就把他们交换过来(升序排列)。
把大(小)的元素往前(后)调

1.3 原理

  1. 从头到尾依次比较相邻的两个元素,如果第一个比第二个大,就交换两个位置;
  2. 第一次比较完,最后一个就是最大数
  3. 重复步骤1,除了最后一个数。
  4. 第二次比较完,最后第二个数就是次大数

1.4 时间复杂度:O(n^2)

最差是:O(n^2),在待排数据正好是反序的,需要进行n-1趟,每次比较n-i (1<=i<=n-1),复杂度是O((n-1)(n-i)),所以就是O(n^2)
最好是:O(1),在待排数据正好是正序的,一遍就可以排序完。复杂度是O(n)
因此冒泡排序总的平均时间复杂度为O(n^2)。

1.5 空间复杂度:1

1.6 是否稳定:稳定

1.7 代码例子

#include    <stdio.h>

/* 交换两个值 */
void mySwap(int *i, int *j)
{
	int iTmp = *i;
	*i = *j;
	*j = iTmp;
}

/* 打印 */
void myPrint(int arr[], int len)
{
	for (int iLoop = 0; iLoop < len; iLoop++)
	{
		printf("%d ",arr[iLoop]);
	}
	printf("\n");
}

void bubble_sort(int arr[], int len)
{
	/* 1. 注意这里i<len-1 n个数,最多进行n-1 次排序 
	如:10个数,比较9次即可 */
	for (int i = 0; i < len-1; i++) 
	{
		/* 2. 注意这里:j<len-i-1,就是后面(已经比较的)的不用进行比较了, 
		或者说 排序过程中,分为有序区和无序区*/
		for (int j = 0; j < len - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				mySwap(&arr[j], &arr[j + 1]);
			}
		}
	}
}

void test_bubble()
{
	printf("test_bubble start \n");
	int aiBubbleArr[] = {5, 8, 3, 14, 1 };
	int arrLen = sizeof(aiBubbleArr)/sizeof(aiBubbleArr[0]);
	myPrint(aiBubbleArr, arrLen);
	bubble_sort(aiBubbleArr, arrLen);
	myPrint(aiBubbleArr, arrLen);
	printf("test_bubble end \n");
}

int main()
{
	test_bubble();
	return 0;
}

结果:
test_bubble start
5 8 3 14 1
1 3 5 8 14
test_bubble end

2. 选择排序

2.1 选择思想

每次选择最小(大)的元素放到开头(结尾)。

2.2 原理

  1. 从头到尾遍历找到最小的元素放到开始的位置
  2. 然后,再从未排序的找出最小的元素放到已排数的尾部
  3. 继续……直到所有元素均排序完毕

2.3 时间复杂度:O(n^2)

选择排序比冒泡排序快,因为交换次数比冒泡排序少多了。

2.4 空间复杂度:1

2.5 是否稳定:不稳定

序列5 8 5 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中两个5的相对前后顺序就被破坏了,所以选择排序是一个不稳定的排序算法。

2.6 代码例子

#include    <stdio.h>

/* 交换两个值 */
void mySwap(int *i, int *j)
{
	int iTmp = *i;
	*i = *j;
	*j = iTmp;
}

/* 打印 */
void myPrint(int arr[], int len)
{
	for (int iLoop = 0; iLoop < len; iLoop++)
	{
		printf("%d ",arr[iLoop]);
	}
	printf("\n");
}


void select_sort(int arr[], int len)
{
	int iMinTmp = 0;
	
	for(int i = 0; i < len -1; i++)
	{
		iMinTmp = i;
		for(int j = i + 1; j < len; j++)
		{
			if(arr[iMinTmp] > arr[j])
			{
				iMinTmp = j;
			}
		}
		
		if(iMinTmp != i)
		{
			mySwap(&arr[iMinTmp], &arr[i]);
		}
	}
}

void test_select()
{
	printf("test_select start \n");
	int aiselectArr[] = {5, 8, 3, 14, 1 };
	int arrLen = sizeof(aiselectArr)/sizeof(aiselectArr[0]);
	myPrint(aiselectArr, arrLen);
	select_sort(aiselectArr, arrLen);
	myPrint(aiselectArr, arrLen);
	printf("test_select end \n");
}

int main()
{
	test_select();
	return 0;
}

3. 快速排序

3.1 快排

  1. 找出一个基准(如使用待排的第一个数),然后将数据分割成两个部分,一部分比基准都大,另外一部分比基准都小。然后递归。
  2. 快速排序(Quicksort)是对冒泡排序的一种改进

3.1.1 思想

快速排序思想----分治法

  1. 先从数列中取出一个数作为基准数。
    2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
    3.再对左右区间重复第二步,直到各区间只有一个数。

3.1.2 效率

快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用。

3.2 步骤

  1. 先找出一个基准(分界值),将数据分成左右两个部分(不符合就和冒泡一样的交换数据);
  2. 将大于或等于基准的数放到右边,将小于基准的数放到左边;
  3. 然后递归进行左右部分进行排序

3.3 时间复杂度:O(nlog(n))

平均: O(nlog(n))
最差:O(n^2)
最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。
这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2)。

3.4 空间复杂度:O(1)

3.5 是否稳定:不稳定

假设待排序数组: a = [ 1, 2, 2, 3, 4, 5, 6 ];
在快速排序的随机选择比较子(即pivot)阶段:
若选择a[2](即数组中的第二个2)为比较子,而把大于等于比较子的数均放置在大数数组中,则a[1](即数组中的第一个2)会到pivot的右边, 那么数组中的两个2非原序(这就是“不稳定”)。
若选择 a[1] 为比较子,而把小于等于比较子的数均放置在小数数组中,则数组中的两个 2 顺序也非原序 。
这就说明,quick sort是不稳定的。

参考: https://www.cnblogs.com/zhangguicheng/p/12906102.html

3.6 代码例子

#include    <stdio.h>

/* 交换两个值 */
void mySwap(int *i, int *j)
{
	int iTmp = *i;
	*i = *j;
	*j = iTmp;
}

/* 打印 */
void myPrint(int arr[], int len)
{
	for (int iLoop = 0; iLoop < len; iLoop++)
	{
		printf("%d ",arr[iLoop]);
	}
	printf("\n");
}

int quick_sort_partion(int arr[], int low, int high)
{
	int pivot = arr[low];
	while(low < high)
	{
		while((low < high) && (arr[high] >= pivot))
		{
			high--;
		}
		mySwap(&arr[low], &arr[high]);
		
		while((low < high) && (arr[low] <= pivot))
		{
			low++;
		}
		mySwap(&arr[low], &arr[high]);
	}
	return low;
}

void quick_sort_proc(int arr[], int low, int high)
{
	if(low < high)
	{
		int pivot = quick_sort_partion(arr, low, high);
		quick_sort_proc(arr, low, pivot - 1);
		quick_sort_proc(arr, pivot + 1, high);
	}
}

void quick_sort(int arr[], int len)
{
	quick_sort_proc(arr, 0, len - 1);
}

void test_quick()
{
	printf("test_quick start \n");
	int aiQuickArr[] = {5, 8, 3, 14, 1 };
	int arrLen = sizeof(aiQuickArr)/sizeof(aiQuickArr[0]);
	myPrint(aiQuickArr, arrLen);
	quick_sort(aiQuickArr, arrLen);
	myPrint(aiQuickArr, arrLen);
	printf("test_quick end \n");
}

int main()
{
	test_quick();
	return 0;
}

3.7 参考:

https://blog.csdn.net/morewindows/article/details/6684558

猜你喜欢

转载自blog.csdn.net/lqy971966/article/details/107367429