• 数据结构与算法分析


    大二其实已经学习过了快排,但是现在基本上已经忘记了快排的细节和具体实现。现在为了准备可能的面试,重新复习一下快速排序。温故知新,古人诚不欺我。主要以《算法导论》为教材。

    《算法导论》这本书在介绍算法时,首先给出算法的描述,也就是伪码,然后就是算法的正确性证明和优化。本文首先也是给出算法的伪码,至于正确性的证明,还是看自己能否胜任。

    快排的大致框架

    QUICKSORT(A,p,r)
    if p < r
        then q = PARTITION(A,p,r)
        QUICKSORT(A,p,q-1)
        QUICKSORT(A,q+1,r)
    

     了解快排,就会知道快排的核心思想就是每次实现这样一个数组:选定数组中某一个值,确保该值左边的元素都比它小,右边的元素都比它大。这样虽然不能保证改值左边和右边的元素一定是有序的,但是一定能够保证该值在排序后的数组中的相对位置不会改变。比如说A[i]此时在第i个位置,当整个数组排完序之后,A[i]一定还是在i。这样也就知道为什么上面代码中递归的时候不用包含q的值,因为它的位置已经确定了。

    经过以上的分析,就不难在实际编码中写出快排的大致框架了。

    快排的划分

    显而易见,快排采用的是分治的思想。每次将一个任务分为两个或者多个部分来解决。但是如何划分其实才是快排的难点和重点。在面试的工程中被问道了这个问题,自己完全忘了如何划分。

    如果要保证每次排序后的数组都满足左边的都比指定元素要小,右边则都要大,必须要选择一个参照值作为比较的对象,这个参考值就叫做主元。确定了组员,就开始遍历比较。

    假设每次选取的都是最右边的元素作为主元,那么就可以从左到右来比较和确定元素的位置。具体见下面的伪码。

    PARTITION(A,p,r)
    x = A[r]
    i = p - 1
    for j : p to r
        do if A[j] < x
                then i = i + 1
                exchange(A[i],A[j])
    exchange(A[i+1],A[r])
    return i+1

    大致的策略就是尽量让比主元小的元素排在前面。就这样,很神奇的整个数组就排完序了。

    C代码实现

    /*************************************************************************
        > File Name: myfiles/C/sort/quicksort.c
        > Author: ma6174
        > Mail: ma6174@163.com 
        > Created Time: 2014年10月06日 星期一 11时38分28秒
     ************************************************************************/
    
    #include<stdio.h>
    #define maxn 100
    int A[maxn];
    int n;
    /* 输入数据 */
    void read()
    {
    	printf("input the num:
    ");
    	scanf("%d",&n);
    	int i;
    	for(i = 0; i < n; i++) {
    		scanf("%d",&A[i]);
    	}
    }
    /* 分治 */
    int partition(int A[], int p, int r)
    {
    	int key = A[r];
    	int i = p - 1;
    	int j;
    	for(j = p; j < r; j++) {
    		if(A[j] < key) { /* 目前为止,没有等于好也可以正确执行,但是我不确定要不要等号*/
    			i++;
    			int temp = A[i];
    			A[i] = A[j];
    			A[j] = temp;
    		}
    	}
    	int temp = A[i+1];
    	A[i+1] = key;
    	A[r] = temp;
    	return i+1;
    }
    /* 快排 */
    void quick_sort(int A[], int p, int r)
    {
    	if(p < r) {
    		int q = partition(A,p,r);
    		quick_sort(A,p,q-1);
    		quick_sort(A,q+1,r);
    	}
    }
    /* 输出 */
    void write() 
    {
    	printf("the sorted array:
    ");
    	int i;
    	for(i = 0; i < n; i++) {
    		printf("%d ",A[i]);
    	}
    	printf("
    ");
    }
    int main()
    {
    	read();
    	quick_sort(A,0,n-1);
    	write();
    }
    

     快排的优化

    如果自己在草稿纸上写写整个快排的步骤,不难发现对于逆序的序列,上面的快排版本的复杂度是O(n2),所以有优化。很简单,每次随机的选取一个元素作为主元。

    -end-

  • 相关阅读:
    从左边或右边删除字符串-python 使用lstrip
    MapReduce- 学习9313第一节记录 材料源于百度百科
    138. (待解决)复制带随机指针的链表
    19. 删除链表的倒数第N个节点-链表(leetcode)
    347.前k个高频元素-counter(leetcode)
    python二进制、十进制、8进制、16进制转换(转)
    POJ 1715
    POJ 1306
    POJ 2436
    POJ 2249
  • 原文地址:https://www.cnblogs.com/mr-zys/p/4008698.html
Copyright © 2020-2023  润新知