【算法导论】快速排序

来源:互联网 发布:华为ar 限制 mac 编辑:程序博客网 时间:2024/05/18 02:02

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


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

参考牛人博客: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-1using 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<rwhile (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;}



1 0