各种排序方法源码及复杂度分析(二)

八、快速排序

快速排序是一个神奇的算法,他采用了递归的算法,找到数列的第一个数,整个数列比他小的数放在他的左边,比他大的数放在他的右边,实现逻辑是:把数列的第一个数当做一个标志mark,然后接下来的每个数都和他比较大小,如果小不移动,如果比mark大,则和第一个比mark大的数交换位置。这里用到了双指针,一个指针指向循环的数组下标,一个指针指向比mark小的所有数的最后一位,只要第一个指针指向的数的值大于mark的值,那么第二个指针加一,第一个指针指向的数和第二个指针指向的数交换位置。
代码实现如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int partition(int *data, int begin, int end) {
	int mark = data[begin];
	int i = 0, k = begin;
	int tmp;
	for (i = begin + 1; i <= end; i++) {
		if (data[i] <= mark) {
			k++;
			if (k < i) {
				tmp = data[k];
				data[k] = data[i];
				data[i] = tmp;
			}
		}
	}
	tmp = data[begin];
	data[begin] = data[k];
	data[k] = tmp;
	return k;
}

//快速排序
void QuickSort(int *data, int begin, int end) {
	int ret;
	if (begin < end) {
		ret = partition(data, begin, end);
		QuickSort(data, begin, ret - 1);
		QuickSort(data, ret + 1, end);
	}
}

int main(void) {
	int data[] = { 70, 4, 8, 23, 5, 7, 9, 1, 4, 65, 23, 456, 67, 13, 24, 4656,
			352, 79, 278, 41 };
	int i;
	int length = sizeof(data) / sizeof(int);
	QuickSort(data, 0, length - 1);
	for (i = 0; i < length; i++) {
		printf("%d ", data[i]);
	}
	return 0;
}
复杂度分析:
最差复杂度是n^2,最优的复杂度是n*lg(n),平均的复杂度是n*lg(n),如何确保他的复杂度总是n*lg(n)呢?有两种方法,一种是随机排序序列中的元素,另外一种是随机选择主元,这种方法称为“随机化快速排序”。“随机化快速排序的优点是:无需对输入序列的分布做任何假设
C语言中Static关键字大体有三个作用:
1. static具有隐藏的作用,举个例子,如果在a.c文件中写了一个msg()函数以及定义了一个变量a,在另外一个main.c函数中可以调用msg函数,也可以引用变量a,为什么呢?是因为这个msg()函数和变量a没有被隐藏,main.c文件可以找到他们,如果是static msg() 或者static a,这样main.c就找不到他了,msg()函数和变量a只能在a.c文件中被调用。
2. 保持变量内容的持久,存储在静态区的数据会在程序第一次运行的时候完成初始化,也是唯一的初始化。利用这个性质可以计算一个函数被调用的次数。
例如:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void count() {
	static int num = 0;
	num++;
	printf(" I have been called %d timesn\n", num);
}
int main() {
	int i;
	for (i = 1; i <= 3; i++) {
		count();
	}
	return 0;
}
打印结果是:
 I have been called 1 timesn
 I have been called 2 timesn
 I have been called 3 timesn
3. static变量默认初始化为0,保存在静态数据区,静态数据区变量默认都是0,某些时候这个特性可以减少程序员的工作量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值