《算法导论》笔记 第8章 8.2计数排序

【笔记】

计数排序假设n个输入元素中的每一个都是介于0到k之间的整数,此处k为某个整数。当k=O(n)时,计数排序的运行时间为 Θ(n)。

计数排序是稳定的。

void countingSort(int A[],int B[],int n,int k) {
    int C[MAXK];
    for (int i=0;i<=k;i++) {
        C[i] = 0;
    }
    for (int j=1;j<=n;j++) {
        C[A[j]]++;
    }
    for (int i=1;i<=k;i++) {
        C[i] = C[i] + C[i-1];
    }
    for (int j=n;j>=1;j--) {
        B[C[A[j]]] = A[j];
        C[A[j]]--;
    }
}

【练习】


8.2-1 说明COUNTING-SORT在数组 A = <6,0,2,0,1,3,4,6,1,3,2> 上的处理过程。

C = <2,2,2,2,1,0,2>

C = <2,4,6,8,9,9,11>

C[i]表示最后一个值为i的元素应在的位置。

倒序将A[i]中的元素复制到B[i]中的目标位置。


8.2-2 证明 COUNTING-SORT 是稳定的。

对最后的一次循环应用循环不变式证明B数组是稳定的。

初始化:在第一次迭代前,B中没有元素,是稳定的。

保持:某次迭代中,C[i]数组中,存储的是A中小于等于i的数有多少个。
即表示小于等于A[j]的最后一个元素,应在的位置,将A[j]放入B中后,C[A[j]]--。

此时,之后的值为A[j]的元素数减去一。所以j之前的与j相同的数不会放到A[j]之后,因此A[j..n]仍是稳定的。

终止:最后一次迭代后,所有元素都复制到了B中,因此B[1..n]是稳定的。


8.2-3 在 COUNTING-SORT 过程中,假设最后一次循环的fao首部改为 for j <- 1 to length[A],证明该算法仍能正常工作。修改后的算法是稳定的吗?

在每次循环中A[j]被放到小于等于A[j]的最后一个元素所在的位置,而A[j]不一定是最后一个小于等于A[j]的元素,但一定等于A[j]。

因此该算法仍能正常工作,却不再稳定。


8.2-4 请给出一个算法,使之对于给定的介于0到k之间的n个整数进行预处理,并能在O(1)时间内,回答出输入的整数中有多少个落在区间[a..b]内。你给出的算法的预处理的时间应该是Θ(n+k)。

void prepare(int A[],int C[],int n,int k) {
    for (int i=0;i<=k;i++) {
        C[i] = 0;
    }
    for (int j=1;j<=n;j++) {
        C[A[j]]++;
    }
    for (int i=1;i<=k;i++) {
        C[i] = C[i] + C[i-1];
    }
}
int getAns(int C[],int L,int R) {
    if (L==0) return C[R];
    return C[R]-C[L-1];
}

查询时应保证0<=L<=R<=k。




posted on 2014-04-11 15:15  电子幼体  阅读(255)  评论(0编辑  收藏  举报

导航