Introduction to Algorithms 算法导论 第2章 算法入门 学习笔记及习题解答

本文是《Introduction to Algorithms》第二章的学习笔记,主要探讨了算法的正确性分析、资源需求预测,以及通用处理器和随机存取RAM的实现模型。介绍了插入排序的最坏情况运行时间为O(n^2)。同时,解释了分治法在合并排序中的应用,并详细展示了冒泡排序的正确性和效率分析。此外,还讨论了霍纳规则在计算多项式中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.1 插入排序

插入排序解决的问题:
    输入:n个数构成的序列<a1, a2, ..., an>
    输出:排序输入序列<a1, a2, ..., an>为<a1', a2', ..., an'>,满足a1' ≤ a2' ≤ ... ≤ an'

伪码:
    INSERTION-SORT(A)
      for j <- 2 to length[A]
        do key <- A[j]
            i <- j - 1
            while i > 0 and A[i] > key
                do A[i+1] <- A[i]
                    i <- i - 1
            A[i+1] = key

C代码:(C的数组下标从0开始,而伪码中从1开始)
void insertion_sort(int *arr, size_t size)
{
    int i, j, key;

    assert(NULL != arr);

    for (j = 1; j < size; ++j) {
        key = arr[j];

        for (i = j - 1; i >= 0 && arr[i] > key; --i)
            arr[i+1] = arr[i];

        arr[i+1] = key;
    }
}

正确性分析:

    说明:
        插入算法在执行循环之前,A[1,j-1]是已排好序的,而每次循环都保持这个情况,因此当j从2到length[A]循环完成后,整个数组已排序。
    初始:
        j=2,A[1,j-1]只包含一个元素A[1],因此是已排序的;
    保持:
        对于任意j(2 ≤ j ≤ length[A]),保存A[j]到key
        内部循环总是从A[j-1], A[j-2], ..., A[1]序列中依次查找所有大于A[j]的值并依次后移。
        当循环结束时,A[i+1,j]中存放所有大于key的值,而A[1,i-1]中存放所有不大于key的值,且A[i]是空闲的。
        存放key到A[i]。
        因此每次循环后,A[1,j]是有序的。
    退出:
        j > length[A]时循环结束,此时A[1,length[A]]全部有序。

数学归纳法证明:
    当j=2时,A[1,j-1]只包含一个元素A[1],因此肯定是有序的。
    假定对于任意j=m(2 ≤ m < length[A]),循环完成后有A[1,j]有序
    则当j=m+1时:
        A[1,m]肯定有序。
        保存A[m+1]到key。
        内层循环结束时,A[1,i]子数组中所有元素不大于key,而A[i+2,m+1]子数组中所有元素大于key,A[i+1]不持有有效数据。
        保存key到A[i+1]。
        综上可知:A[1,m+1]此时是有序的。

    因此对于所有的j(2 ≤ j ≤ length[A]),在任意时刻,有A[1,j]有序。
    当循环迭代到j=length[A]算法结束时,数组A已排序。

测试程序:
    可以通过如下程序测试插入排序算法的正确性。其中辅助函数print_arr、init_arr可能在以后多次用到:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void insertion_sort(int *arr, size_t size)
{
	int key;
	int i, j;

	assert(NULL != arr);

	for (j = 1; j < size; ++j) {
		key = arr[j];
		for (i = j - 1; i >= 0 && arr[i] > key; --i)
			arr[i+1] = arr[i];
		arr[i+1] = key;
	}
}

void print_arr(const int *arr, size_t size, const char *info)
{
	int i;

	assert(NULL != arr);

	printf("%s: ", info);
	for (i = 0; i < size; ++i)
		printf("%d ", arr[i]);
	printf("\n");
}

void init_arr(int *arr, size_t size)
{
	int i;

	assert(NULL != arr);

	srand((unsigned int)time(NULL));

	for (i = 0; i < size; ++i)
		arr[i] = rand()%100;
}

int main()
{
	int arr[10];

	init_arr(arr, 10);
	print_arr(arr, 10, "before");
	insertion_sort(arr, 10);
	print_arr(arr, 10, "after");

	return 0;
}


习题:

2.1-1 以图2-2为模型,说明INSERTION-SORT在数组A=<31,41,59,26,41,58>上的执行过程。
如下:
    31,    41(j), 59,    26,    41,    58
    31(j), 41,    59(j), 26,    41,    58
    26,    31,    41,    59(j), 41,    58
    26,    31,    41,    41,    59(j), 58
    26,    31,    41,    41,    58,    59(j)
标注为x(j)的元素表示此时正在以j执行循环。

2.1-2 重写过程INSERTION-SORT,使之按非升序(而不是按非降序)排序。
只需要更改一行:
更改
    while i > 0 and A[i] > key

    while i > 0 and A[i] < key
即可。

2.1-3 考虑下面的查找问题:
    输入:一列数A=<a1,a2,…,an>和一个值V。
    输出:下标i,使得V=A[i],或者当V不再A中出现时为NIL。
写出针对这个问题的线性查找的伪代码,它顺序地扫描整个序列以查找V。利用循环不变式证明算法的正确性。确保所给出的循环不变式满足三个必要的性质。
FIND-LINEAR(A, v, i)
    i <- NIL
    j <- 1
    while j ≤ length[A] and A[j] != v
        do j <- j + 1
    if j ≤ length[A]
        then i <- NIL
int find_linear(const int *arr, size_t size, int v)
{
    int i;

    for (i = 0; i < size && arr[i] != v; ++i);

    if (i == size) i = -1;    /* -1 means NIL */

    return (int)i;
}

证明:
    初始:
        i=NIL,初始化为未查找到。

    保持:
        从j=1到length[A],依次判断,如果A[j]等于v,则结束循环。

    退出:
        循环结束时,判断j是否有效
        如果j在有效范围(小于等于length[A]),则证明查找成功,因此设置i为正确的索引。
        否则,循环因为越界结束,v没有找到,i依然为NIL。

2.1-4 有两个各存放在数组A和B中的n位二进制整数,考虑它们的相加问题。两个整数的和以二进制形式存放在具有(n+1)个元素的数组C中。请给出这个问题的形式化描述,并写出伪代码。

存储说明:最高位存在数组的第一个元素中,最低位存在数组的最后一个元素中。
    因为A/B各有n个元素而C有n+1个元素,因此对于任意i(1 ≤ i ≤ n),A[i]、B[i]和C[i+1]总在相同位(权数)。如下:

                
中文名: 算法导论 原名: Introduction to Algorithms 作者: Thomas H. Cormen Ronald L. Rivest Charles E. Leiserson Clifford Stein 资源格式: PDF 版本: 文字版 出版社: The MIT Press书号: 978-0262033848发行时间: 2009年09月30日 地区: 美国 语言: 英文 简介: 内容介绍: Editorial Reviews Review "In light of the explosive growth in the amount of data and the diversity of computing applications, efficient algorithms are needed now more than ever. This beautifully written, thoughtfully organized book is the definitive introductory book on the design and analysis of algorithms. The first half offers an effective method to teach and study algorithms; the second half then engages more advanced readers and curious students with compelling material on both the possibilities and the challenges in this fascinating field." —Shang-Hua Teng, University of Southern California "Introduction to Algorithms, the 'bible' of the field, is a comprehensive textbook covering the full spectrum of modern algorithms: from the fastest algorithms and data structures to polynomial-time algorithms for seemingly intractable problems, from classical algorithms in graph theory to special algorithms for string matching, computational geometry, and number theory. The revised third edition notably adds a chapter on van Emde Boas trees, one of the most useful data structures, and on multithreaded algorithms, a topic of increasing importance." —Daniel Spielman, Department of Computer Science, Yale University "As an educator and researcher in the field of algorithms for over two decades, I can unequivocally say that the Cormen book is the best textbook that I have ever seen on this subject. It offers an incisive, encyclopedic, and modern treatment of algorithms, and our department will continue to use it for teaching at both the graduate and undergraduate levels, as well as a reliable research reference." —Gabriel Robins, Department of Computer Science, University of Virginia Product Description Some books on algorithms are rigorous but incomplete; others cover masses of material but lack rigor. Introduction to Algorithms uniquely combines rigor and comprehensiveness. The book covers a broad range of algorithms in depth, yet makes their design and analysis accessible to all levels of readers. Each chapter is relatively self-contained and can be used as a unit of study. The algorithms are described in English and in a pseudocode designed to be readable by anyone who has done a little programming. The explanations have been kept elementary without sacrificing depth of coverage or mathematical rigor. The first edition became a widely used text in universities worldwide as well as the standard reference for professionals. The second edition featured new chapters on the role of algorithms, probabilistic analysis and randomized algorithms, and linear programming. The third edition has been revised and updated throughout. It includes two completely new chapters, on van Emde Boas trees and multithreaded algorithms, and substantial additions to the chapter on recurrences (now called "Divide-and-Conquer"). It features improved treatment of dynamic programming and greedy algorithms and a new notion of edge-based flow in the material on flow networks. Many new exercises and problems have been added for this edition. As of the third edition, this textbook is published exclusively by the MIT Press. About the Author Thomas H. Cormen is Professor of Computer Science and former Director of the Institute for Writing and Rhetoric at Dartmouth College. Charles E. Leiserson is Professor of Computer Science and Engineering at the Massachusetts Institute of Technology. Ronald L. Rivest is Andrew and Erna Viterbi Professor of Electrical Engineering and Computer Science at the Massachusetts Institute of Technology. Clifford Stein is Professor of Industrial Engineering and Operations Research at Columbia University. 目录: Introduction 3 1 The Role of Algorithms in Computing 5 1.1 Algorithms 5 1.2 Algorithms as a technology 11 2 Getting Started 16 2.1 Insertion sort 16 2.2 Analyzing algorithms 23 2.3 Designing algorithms 29 3 Growth of Functions 43 3.1 Asymptotic notation 43 3.2 Standard notations and common functions 53 4 Divide-and-Conquer 65 4.1 The maximum-subarray problem 68 4.2 Strassen's algorithm for matrix multiplication 75 4.3 The substitution method for solving recurrences 83 4.4 The recursion-tree method for solving recurrences 88 4.5 The master method for solving recurrences 93 4.6 Proof of the master theorem 97 5 Probabilistic Analysis and Randomized Algorithms 114 5.1 The hiring problem 114 5.2 Indicator random variables 118 5.3 Randomized algorithms 122 5.4 Probabilistic analysis and further uses of indicator random variables 130 II Sorting and Order Statistics Introduction 147 6 Heapsort 151 6.1 Heaps 151 6.2 Maintaining the heap property 154 6.3 Building a heap 156 6.4 The heapsort algorithm 159 6.5 Priority queues 162 7 Quicksort 170 7.1 Description of quicksort 170 7.2 Performance of quicksort 174 7.3 A randomized version of quicksort 179 7.4 Analysis of quicksort 180 8 Sorting in Linear Time 191 8.1 Lower bounds for sorting 191 8.2 Counting sort 194 8.3 Radix sort 197 8.4 Bucket sort 200 9 Medians and Order Statistics 213 9.1 Minimum and maximum 214 9.2 Selection in expected linear time 215 9.3 Selection in worst-case linear time 220 III Data Structures Introduction 229 10 Elementary Data Structures 232 10.1 Stacks and queues 232 10.2 Linked lists 236 10.3 Implementing pointers and objects 241 10.4 Representing rooted trees 246 11 Hash Tables 253 11.1 Direct-address tables 254 11.2 Hash tables 256 11.3 Hash functions 262 11.4 Open addressing 269 11.5 Perfect hashing 277 12 Binary Search Trees 286 12.1 What is a binary search tree? 286 12.2 Querying a binary search tree 289 12.3 Insertion and deletion 294 12.4 Randomly built binary search trees 299 13 Red-Black Trees 308 13.1 Properties of red-black trees 308 13.2 Rotations 312 13.3 Insertion 315 13.4 Deletion 323 14 Augmenting Data Structures 339 14.1 Dynamic order statistics 339 14.2 How to augment a data structure 345 14.3 Interval trees 348 IV Advanced Design and Analysis Techniques Introduction 357 15 Dynamic Programming 359 15.1 Rod cutting 360 15.2 Matrix-chain multiplication 370 15.3 Elements of dynamic programming 378 15.4 Longest common subsequence 390 15.5 Optimal binary search trees 397 16 Greedy Algorithms 414 16.1 An activity-selection problem 415 16.2 Elements of the greedy strategy 423 16.3 Huffman codes 428 16.4 Matroids and greedy methods 437 16.5 A task-scheduling problem as a matroid 443 17 Amortized Analysis 451 17.1 Aggregate analysis 452 17.2 The accounting method 456 17.3 The potential method 459 17.4 Dynamic tables 463 V Advanced Data Structures Introduction 481 18 B-Trees 484 18.1 Definition of B-trees 488 18.2 Basic operations on B-trees 491 18.3 Deleting a key from a B-tree 499 19 Fibonacci Heaps 505 19.1 Structure of Fibonacci heaps 507 19.2 Mergeable-heap operations 510 19.3 Decreasing a key and deleting a node 518 19.4 Bounding the maximum degree 523 20 van Emde Boas Trees 531 20.1 Preliminary approaches 532 20.2 A recursive structure 536 20.3 The van Emde Boas tree 545 21 Data Structures for Disjoint Sets 561 21.1 Disjoint-set operations 561 21.2 Linked-list representation of disjoint sets 564 21.3 Disjoint-set forests 568 21.4 Analysis of union by rank with path compression 573 VI Graph Algorithms Introduction 587 22 Elementary Graph Algorithms 589 22.1 Representations of graphs 589 22.2 Breadth-first search 594 22.3 Depth-first search 603 22.4 Topological sort 612 22.5 Strongly connected components 615 23 Minimum Spanning Trees 624 23.1 Growing a minimum spanning tree 625 23.2 The algorithms of Kruskal and Prim 631 24 Single-Source Shortest Paths 643 24.1 The Bellman-Ford algorithm 651 24.2 Single-source shortest paths in directed acyclic graphs 655 24.3 Dijkstra's algorithm 658 24.4 Difference constraints and shortest paths 664 24.5 Proofs of shortest-paths properties 671 25 All-Pairs Shortest Paths 684 25.1 Shortest paths and matrix multiplication 686 25.2 The Floyd-Warshall algorithm 693 25.3 Johnson's algorithm for sparse graphs 700 26 Maximum Flow 708 26.1 Flow networks 709 26.2 The Ford-Fulkerson method 714 26.3 Maximum bipartite matching 732 26.4 Push-relabel algorithms 736 26.5 The relabel-to-front algorithm 748 VII Selected Topics Introduction 769 27 Multithreaded Algorithms Sample Chapter - Download PDF (317 KB) 772 27.1 The basics of dynamic multithreading 774 27.2 Multithreaded matrix multiplication 792 27.3 Multithreaded merge sort 797 28 Matrix Operations 813 28.1 Solving systems of linear equations 813 28.2 Inverting matrices 827 28.3 Symmetric positive-definite matrices and least-squares approximation 832 29 Linear Programming 843 29.1 Standard and slack forms 850 29.2 Formulating problems as linear programs 859 29.3 The simplex algorithm 864 29.4 Duality 879 29.5 The initial basic feasible solution 886 30 Polynomials and the FFT 898 30.1 Representing polynomials 900 30.2 The DFT and FFT 906 30.3 Efficient FFT implementations 915 31 Number-Theoretic Algorithms 926 31.1 Elementary number-theoretic notions 927 31.2 Greatest common divisor 933 31.3 Modular arithmetic 939 31.4 Solving modular linear equations 946 31.5 The Chinese remainder theorem 950 31.6 Powers of an element 954 31.7 The RSA public-key cryptosystem 958 31.8 Primality testing 965 31.9 Integer factorization 975 32 String Matching 985 32.1 The naive string-matching algorithm 988 32.2 The Rabin-Karp algorithm 990 32.3 String matching with finite automata 995 32.4 The Knuth-Morris-Pratt algorithm 1002 33 Computational Geometry 1014 33.1 Line-segment properties 1015 33.2 Determining whether any pair of segments intersects 1021 33.3 Finding the convex hull 1029 33.4 Finding the closest pair of points 1039 34 NP-Completeness 1048 34.1 Polynomial time 1053 34.2 Polynomial-time verification 1061 34.3 NP-completeness and reducibility 1067 34.4 NP-completeness proofs 1078 34.5 NP-complete problems 1086 35 Approximation Algorithms 1106 35.1 The vertex-cover problem 1108 35.2 The traveling-salesman problem 1111 35.3 The set-covering problem 1117 35.4 Randomization and linear programming 1123 35.5 The subset-sum problem 1128 VIII Appendix: Mathematical Background Introduction 1143 A Summations 1145 A.1 Summation formulas and properties 1145 A.2 Bounding summations 1149 B Sets, Etc. 1158 B.1 Sets 1158 B.2 Relations 1163 B.3 Functions 1166 B.4 Graphs 1168 B.5 Trees 1173 C Counting and Probability 1183 C.1 Counting 1183 C.2 Probability 1189 C.3 Discrete random variables 1196 C.4 The geometric and binomial distributions 1201 C.5 The tails of the binomial distribution 1208 D Matrices 1217 D.1 Matrices and matrix operations 1217 D.2 Basic matrix properties 122
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值