您的位置:首页 > 其它

【算法导论】快速排序

2014-11-19 21:29 225 查看
搞这一行还是始终绕不过数据结构算法这一个坎,自己不是科班出身,基础不好,还是脚踏实地一步一步的开始学,就从今天开始。

起步是什么呢,搞个简单一点的,快速排序:

参考牛人博客:http://blog.csdn.net/morewindows/article/details/6684558

理解:

1、取数组中的第一个数为key值,将一个数组分为两组,如果是想从大到小那么左边的组(数组序数小的组)放比key大的数组元素,右边的组(数组序数小的组)放比key小的数组元素,当这样一次拍完,实际上key这个数组元素所在的最终位置也就是确定了,因为左边都是比他大的,右边都是比他小的数。反之,如果想从小到大排,则反过来即可。

2、第一次分组完之后得到两个组,那么对这两个数组继续进行1中的操作即可

原理就是这样,但是核心问题在于如何进行一次分组?挖坑法,这个叫法确实很形象:

我们认为每一次移动数据都会产生一个坑,假设数组是int a[],长度为10,那么第一次int key = a[0],就是挖了第一个坑,假设从小到大排序,我们需要在数组的右半边找一个比其小的数,来填这个坑,我们先让i=0,j=9,如果先看a[j]是不是小于key,如果是则让a[i]=a[j],实际上就是a[0]这个坑被填满了,这时候左半边实际上就相当于找到了一个“合适的数”,那么i++;如果a[j]不小于key,则右边相当于找到了一个”合适的数“,那么j--;当一次a[i]=a[j]操作之后,我们从数组右边找了一个数来填上了左边的一个坑,然后我们就需要从左边找一个数去填刚才a[j]的这个坑,这个数要比key大,也是使用轮询的方法,如果a[i]<key则i++,否则a[j]=a[i]则j--;

每当a[i]=a[j](赋值)的时候就相当于a[i]这个坑被a[j]填满了,那么a[j]就成了新的那个坑;反之如果每当a[j]=a[i](赋值)的时候,那么a[i]就成了新的那个坑,每次循环的判断条件都是i<j,因为左边和右边不能越界,保证左边的小,右边的大,如果当i=j的时候,就认为这一次分组完成了,将a[i]的值赋值为key。

光讲比较抽象,看看代码(C/C++):

#include <iostream>

#define SIZE 10
#define MAX_INDEX SIZE-1

using namespace std;

void travel(int*a);
void maoPaoSort(int* a);
void quickSort(int* a, int l, int r);
int adjustArray(int* a, int l, int r);
int main() {

	int a[] = { 9, 97, 0, -1, 66, 53, 21, -10, 1001, 34 };

	travel(a);

//	maoPaoSort(a);
	quickSort(a, 0, MAX_INDEX);
	travel(a);
	return 0;
}

void travel(int*a) {
	for (int i = 0; i < SIZE; i++) {
		cout << a[i] << ' ';
	}
	cout << endl;
}

/*
 * 冒泡排序法
 */
void maoPaoSort(int* a) {
	int k = SIZE - 2;
	int tmp = 0;
	for (int i = k; i >= 0; i--) {
		for (int j = 0; j < i; j++) {
			//从大到小排序
			if (a[j] < a[j + 1]) {
				tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
			}
		}
	}
}
/*
 * 快速排序,填坑分治法
 */
void quickSort(int* a, int l, int r) {
	if (l < r) {
		int pos = adjustArray(a, l, r);
		quickSort(a, l, pos - 1);
		quickSort(a, pos + 1, r);
	}
}
/*
 * 填坑函数
 */
int adjustArray(int* a, int l, int r) {
	int i = l;
	int j = r;
	int key = a[i];
	//从小到大排序

	//一直循环,条件是l<r
	while (i < j) {
		cout << "i=" << i << ",j=" << j << ",key=" << key << endl;
		//进行后往前查找,寻找比key小的数,去填上一个i的坑

		//先看满足条件,不变,往后继续走的循环
		while (i < j && a[j] >= key) {
			j--;
		}

		if (i < j) {
			a[i] = a[j];
			i++;
		}
		//进行从前往后查找,寻找比key大的数,去填上一个j的坑
		//先看满足条件,不变,往后继续走的循环
		while (i < j && a[i] <= key) {
			i++;
		}

		if (i < j) {
			a[j] = a[i];
			j--;
		}
	}
	//退出时,让中间i=j的位置的值等于key;相当于就是给key找到了最终的位置
	a[i] = key;
	cout << "i=" << i << ",j=" << j << ",key=" << key << endl;

	return i;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: