算法设计与分析基础第三版

课后题答案

一、算法级基础知识

1.算法的基本概念

解决问题的确定方法和有限步骤称为算法,对于计算机科学来说,算法指的是对特定问题的求解步骤的一种描述,是若干条指令的有穷序列。并有以下特性:输入、输出、确定性、有限性、可行性

算法与程序的区别:程序是算法用某种程序设计语言的具体实现,程序设计的实质就是构造解决问题的算法。算法+数据结构=程序,算法的结构和选择依赖于数据结构,所以数据结构是算法设计的基础。

2.算法设计的一般过程(8步骤)

1.充分理解要解决的问题

在设计算法的时候,一定要先搞清楚算法要求处理什么问题、实现哪些功能、预期获得的结果等。

2.数学模型拟制

简单地说,数学模型就是对实际问题的一种数学表达,是数学理论与实际相结合的一门学科。

3.算法详细设计

算法详细设计指的是把算法具体化,即设计出算法的详细规格说明。

4.算法描述

根据前三部分的工作,采用描述工具将算法的具体过程描述下来。

5.算法思路的正确性验证

通过公式定理来验证算法所选择的设计策略及设计思路是否正确。

6.算法分析

算法分析是对算法的效率进行分析,主要是时间效率和空间效率。

7.算法的计算机实现和测试

采用某种程序设计语言来实现算法,并在计算机上进行运行和测试。

8.文档资料的编制

撰写算法的整个设计过程。

3.算法分析(时间、空间复杂度)

算法分析:分析的是性能、效率

1.时间复杂性

时间复杂性是对算法运行时间长短的度量

2.空间复杂性

空间复杂性是对一个算法在运行过程中所占用存储空间大小的度量。

递归算法要分析空间复杂性

4.递归(必考)

子程序(或函数)直接或间接调用自己称为递归。可能分析空间复杂度。

递归算法运行的过程分为两个阶段:递推和回归

(1)递归原理:
1.当子程序(函数/方法)被调用的时候,在数据栈的栈顶 分配 它的 局部变量和形式参数的 存储空间。

2.当子程序返回时,才从栈顶 释放 它的 局部变量和形式参数的 存储空间。

3.子程序运行使用的是栈顶的那一份变量和形式参数。

4.全局变量、静态局部变量和动态分配的变量(new 分配的),分配在"堆"里,不随程序的调用返回而变化。

(2)递归算法的复杂性分析:
1.递归算法的时间复杂性分析
最常用的就是后向代入法

以全排列问题的为例:

全排列算法的时间=复杂性为:O(n!)

2.递归算法的空间复杂性分析
是指算法的递归深度,即算法在执行过程中所需要的用于存储“调用记录”的递归栈的空间大小。

5.基本的数据结构

所谓数据结构,可以定义为:组织一系列相关数据元素的某种方式(组织数据的方式)。

无关系:集合结构

一对一:线性结构,例如:顺序表与链表,栈与队列

一对多:树型结构

多对多:图型结构

(1)顺序表与链表
线性表是最简单、最常用的一种数据结构,一个线性表是n个数据元素的有限序列。

顺序表:把线性表的元素按逻辑次序依次存放在一组地址连续的存储单元,用这种方法存储的线性表简称为顺序表。

链表:链表是线性表的另一种存储方式,其特点是用一组任意的存储单元存储线性表的数据元素,它由一系列的节点组成,节点可以在运行时动态生成。主要有单链表、循环链表、双向链表。

(2)栈与队列
栈:栈可以看成是一种“特殊”的线性表,该线性表限定仅在表尾进行插入和删除操作(先进后出),栈主要应用于表达式的计算、子程序嵌套调用、递归调用等。栈的性质:通常称插入、删除的这一端称为栈顶(Top),另一端称为栈底(Button)。

队列:和栈相反,队列是一种先进先出的线性表,它只允许在表的一端插入 元素,而在另一端删除元素。队列的性质:允许删除的一端称为队头(Front),允许插入的一端称为队尾(Rear)。

(3)树与图
树:数型结构是以分支关系定义的层次结构,它是一种重要的非线性结构。

图:图是一种比线性表和树更为复杂的数据结构,可以用二元组表示,图中的数据元素通常被称为顶点(或节点),数据元素之间的关系称为边,其形式定义为:G=(V,E),集合V是顶点集,集合E是边集。

在线性表中,数据元素之间仅存在线性关系,即每个元素只有一个直接前驱和一个直接后继

在树型结构中,元素之间具有明显的层次关系,每个元素只能和上一层的一个元素相关,但也可以和下一层的多个元素相关。

在图型结构中元素之间的关系可以是任意的,一个图中任意两个元素都可以相关,即每个元素可以有多个前驱和多个后继。

(4)集合
从逻辑结构上看,集合的元素之间没有任何确定的依赖关系,主要考虑集合之间的并、交、和差操作。

二、分治法

概念:分治法,字面上解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同子问题,再把子问题分成更小的子问题,直到最后各个子问题可以简单地直接求解,对各个子问题的解进行合并即得原问题的解。

通常分治法的求解过程都要遵循两大步骤:分解和治理

1.二分查找

二分查找又称为折半查找,它要求待查找的数据元素必须是按关键字大小有序排列的。

(1)二分查找算法实现的非递归形式

int binSearch1(int arr[], int n, int key) {
	int left = 0;
	int right = n - 1;
	int mid;
	while (left <= right) {
		mid = (left + right) / 2;
		if (arr[mid] == key) {
			return mid;}
		else if (arr[mid] > key) {
			right = mid - 1;}
		else if (arr[mid] < key) {
			left = mid + 1;}
	}
	return -1;
}

(2)二分查找算法实现的递归形式

int binSearch2(int arr[], int key, int left, int right) {
	int mid = (left + right) / 2;
	if (left > right) {
		return -1;}
	if (arr[mid] == key) {
		return mid;}
	else if (arr[mid] > key) {
		return binSearch(arr, key, left, mid - 1);}
	else if (arr[mid] < key) {
		return binSearch(arr, key, mid + 1, right);}
}

2.快速排序

快速排序是一种划分交换排序。

int Partition(int arr[], int left, int right) {
		int temp = arr[left];
		int i = left;
		int j = right;
		while (i<j) {
			while (i<j && arr[j]>temp)
			j--;
			if(i<j){
                swap(arr[i], arr[j]);}
			while (i<j && arr[i] <= temp)
			i++;
			if (i<j) {
                swap(arr[i], arr[j--]);}
		}	
		return j;
	}
void QuickSort(int arr[], int left, int right) {
	int mid;
	if (left < right) {
		mid = Partition(arr, left, right);
		QuickSort(arr, left, mid - 1);
		QuickSort(arr, mid + 1, right);
	}
}

猜你喜欢

转载自blog.csdn.net/edgarrr/article/details/127543921