Introduction to Algorithms (算法导论) 学习笔记 -- Chapter 9

来源:互联网 发布:淘宝一个皇冠要多少丹 编辑:程序博客网 时间:2024/04/29 04:26

Chapter 9 Medians and Order Statistics (中位数和顺序统计)


n个元素中查找最小或最大元素,需要进行n-1次比对。


同时查找最小和最大的元素,最坏情况下需要进行⌈3n/2 - 2⌉次比较(⌈⌉为上取整)

证明:

对于n为奇数,初始设置min和max均为第一个元素,剩下n-1个元素为偶数,

对于n为偶数,比对前两个元素,设置较小的为min,较大的为max,剩下n-2个元素为偶数。


两两比对剩余的元素,较大者与max比对,较小者与min比对,并设置新的max和min。可见每对元素需要进行三次比较。因此:

对于奇数,共需比对的次数等于3(n-1)/2 = ⌊3n/2⌋ = ⌈3n/2⌉ - 1 < ⌈3n/2⌉ - 2

对于偶数,共需比对的次数等于1 + 3(n-2)/2 = 3n/2 - 2 = ⌈3n/2⌉ - 2


因此对于任何整数n,同时查找最小最大元素最坏情况下需要进行⌈3n/2 - 2⌉次比较。

#include <stdlib.h>#include <stdio.h>#include <time.h>void max_min(const int *arr, size_t n, int *pmax, int *pmin){int i;if ( 0 == n%2 ) /* even */{if ( arr[0] > arr[1] ){*pmax = arr[0];*pmin = arr[1];}else{*pmax = arr[1];*pmin = arr[0];}i = 2;}else{*pmax = *pmin = arr[0];i = 1;}while ( i < n ){if ( arr[i] > arr[i+1] ){if ( arr[i] > *pmax ) *pmax = arr[i];if ( arr[i+1] < *pmin ) *pmin = arr[i+1];}else{if ( arr[i+1] > *pmax ) *pmax = arr[i+1];if ( arr[i] < *pmin ) *pmin = arr[i];}i += 2;}}void do_min_max(size_t n){if ( n > 0 ){int i, min, max;int *arr = (int*)malloc(n*sizeof(int));if (!arr){fprintf(stderr, "malloc buffer failed, n = %u\n", n);return;}srandom( (unsigned int)time(NULL) );printf("n=%u, arr={ ", n);for ( i = 0; i < n-1; ++i ){arr[i] = random() % (n*100);printf("%03d, ", arr[i]);}arr[i] = random() % (n*100);printf("%03d }", arr[i]);max_min(arr, n, &max, &min);printf(", min=%03d, max=%03d\n", min, max);free(arr);}}int main(int argc, char *argv[]){if ( argc == 1 ){do_min_max(10);}else{int i;for ( i = 1; i < argc; ++i ){size_t n = (size_t)atoi(argv[i]);if ( n == 0 || n > 100 ){fprintf(stderr, "n = %u overflow, valid n is (0,100]\n", n);continue;}do_min_max(n);}}return 0;}/* eof */# compile~$ gcc -Wall -o max_min max_min.c~$ ./max_min~$ ./max_min 8 6 5

Exercises 9.1-1

Show that the second smallest of n elements can be found with n + ⌈lg n⌉ - 2 comparisons in the worst case. (Hint: Also find the smallest element.)

证明在n个元素中查找第二小的元素在最坏情况下需要n+⌈lg n⌉ - 2次比较。

      题外话:如果仅仅需要2n-3次比较,实现将非常简单:第一次获取最小的,并排除在外,需要n-1次比对。然后从n-1个元素中获取最小的即可,此时需要n-2次比对。因此需要2n-3次比较。


证明:

两两比对n个元素,对于较小元素,继续进行两两比对,如果某元素只剩余一个,则直接进入下一轮参加比对。因此,第一轮比对次数为⌊n/2⌋,第二轮比对次数为⌊ ⌊n/2⌋/2 ⌋,以此类推。该过程可以获得一个有n个叶子节点、n-1个内节点的二叉树。每个内节点对应一次比较,因此共有n-1次比较。例如:

1     8     7     4      6     3     5     9      2                         (第一次)---------------------------------------------------   1           4            3           5         2                         (第二次)   ------------------------------------------------         1                        3               2                         (第三次)         ------------------------------------------                      1                           2                         (第四次)                      -----------------------------                                     1
从根一直回朔到最小值所在叶子节点的路径上,令第二小的元素为第二层不等于最小值的节点,然后每层比较一次一直到叶子可得第二小的值。共需⌈lgn⌉ - 1次比较,故共需比较次数为n + ⌈lg n⌉ - 2次。


Exercises 9.1-2: ⋆

Show that ⌈3n/2⌉ - 2 comparisons are necessary in the worst case to find both the maximum and minimum of n numbers. (Hint: Consider how many numbers are potentially either the maximum or minimum, and investigate how a comparison affects these counts.)

证明同时查找最大最小值最坏情况下需要⌈3n/2⌉ - 2次比较(提示:考虑有多少个可能的最大最小值,考虑一次比对对这些值的影响)

参考本文最前面部分,已做证明。

原创粉丝点击