算法导论 chapter2

2.1 插入排序法
输入: n个数的一个序列<a1, a2, ... , an>。
输出: 输入序列的一个排列<a1_, a2_, ... , an_>。
希望被排序的数称为关键词(key)。

插入排序法伪代码:
INSERTION-SORT(A)
1 for j = 1 to A.length-1
2      key = A[j]
3      // Insert A[j] into the sorted squence A[1,..,j-1].
4      i = j - 1
5       while i > 0 and A[i] > key
6           A[i+1] = A[i]
7           i = i - 1
8      A[i+1] = key

算法具体分析:
1.下标j表示需要被插入的数据的索引值
2.在 for循环(循环变量为j)每次迭代的开始,包含元素A[1..j-1]的子列表示当前排列好的序列

算法的c++代码实现:

#include<iostream>

using namespace std;

void insortion_sort(int* A, int n){
	for (int j = 1; j != n; ++j){
		int key = A[j];
		int i = j - 1;
		while (i >= 0 && A[i] > key){
			A[i + 1] = A[i];
			i--;
		}
		A[i + 1] = key;
	}
}

int main()
{
	int A[] = { 2, 4, 6, 7, 3, 1, 9, 10, 56, 34 };
	int n = sizeof(A) / sizeof(A[0]);
	insortion_sort(A, n);
	for (int j = 0; j != n; ++j)
		cout << A[j] << " ";
	cout << endl;
	return 0;
}

2.1习题选做

2.1-3 考虑以下查找问题:
输入: n个数的一个序列A=<a1,...,an>和一个值v
输出: 下标i使得v=A[i]或者当v不在A中出现时,v为特殊值NIL
要求: 线性查找伪代码
我的解答:
线性查找伪代码:
LINEAR-SEARCH(A, v)
1 for j = 0 to A.length-1
2       if A[j] == v
3           return i
4 v = NIL
5 return v

2.1-4 考虑两个n位二进制整数相加的问题,写出伪代码。
我的解答:
分析:两个n为二进制相加,按位从右到左逐位相加(进位位用carry表示)
1)求A[j]和B[j]按位相加后对应C[i],考虑上一位的进位
2)求进位为carry
两个n位二进制相加伪代码:
ADD-BINARY(A, B)
1 for j=0 to n
2      C[j] = 0
3 carry = 0
for j = 0 to n-1
5      C[j] = (A[j] + B[j] + carry ) % 2
6      carry = (A[i] + B[i] +carry) / 2
7 C[n] = carry
8 return C

算法的c++代码实现:
#include<iostream>

using namespace std;


int* add_binary(int* A, int* B){
	const int n = 5;
	static int C[n+1] = { 0 };
	int carry = 0;
	for (int j = 0; j != n; ++j) {
		C[j] = (A[j] + B[j] + carry) % 2;
		carry = (A[j] + B[j] + carry) / 2;
	}
	C[n] = carry;
	for (int j = 0; j != n + 1; ++j){
		cout << C[j] << " ";
	}
	cout << endl;
	return C;
}

int main()
{
	int a[] = { 1, 1, 0, 1, 0 };
	int b[] = { 1, 0, 0, 1, 1 };
	add_binary(a, b);
	return 0;
}


2.2习题选做
2.2-2 选择排序:找出A中最小的元素与A[1]交换,然后选择次小的元素与A[2]交换,以此类推...
选择排序伪代码:
SELECTIVE-SORT(A)
1 for j = 0 to A.length - 2
2      min  = j
3       for i = j +1 to A.length - 1
4           if A[i] < A[min]
5                min = i
6      temp = A[min]
7      A[min] = A[j]
8      A[j] = temp

2.2归并排序法
归并排序法遵循分治模式:
分解:分解待排序的n个元素的序列成各具n/2的两个子序列
解决:使用归并排序递归的排序两个子列
合并:合并两个已排序的子序列以产生已排序的答案

算法具体分析:
1.采用递归调用,当待排列序列的长度为1时,递归“开始回升”
2.归并算法的关键步骤是“合并”,即合并已排好序的两列序列,通过一个辅助的过程MERGE(A, p, q, r)来实现
3.将MERGE作为MERGE-SORT的子函数,MERGE-SORT递归调用自身

合并函数伪代码:
MERGE(A, p, q, r)
1      n1 = q - p + 1
2      n2 = r - q
3       for j = 0 to n1 - 1
4           L[j] = A[p+j]
5      for j = 0 to n2 - 1
6      R[j] = A[q+j]
7      L[n1] = ∞
8      R[n2] = ∞
9      i = 0
10    j = 0
11       for k = p to r
12            if L[i] <= R[j]
13                A[k] = L[i]
14                i = i + 1
15           else A[k]  =R[j]
16                j = j +1

将MERGE作为MERGE-SORT子程序
归并排序伪代码:
MERGE-SORT(A, p, r)
1 q = (p + r) / 2
2 MERGE-SORT(A, p, q)
3 MERGE-SORT(A, q+1, r)
4 MERGE(A, p, q, r)

算法的c++代码实现:
#include<iostream>
using namespace std;

/********************************************/
/* 
merge函数,用于将序列分解合并实现序列,接口如下:
A: 表示待排序的序列,分成两个部分
p: 表示A序列开始的索引值
q:表示两个已排好序序列在A中的分界
r:表示A序列最后的索引值
*/
/********************************************/
void merge(int* A, int p, int q, int r){
	int n1 = q - p + 1;
	int n2 = r - q;
	int *L = new int[n1+1];
	int *R = new int[n2+1];

	for (int i = 0; i < n1; ++i)
		L[i] = A[p + i];
	for (int i = 0; i < n2; ++i)
		R[i] = A[q + 1 + i];
	L[n1] = INT_MAX;  //暂时把INT_MAX(整形最大值)作为哨兵位
	R[n2] = INT_MAX;
	for (int k = p, i = 0, j = 0; k <= r; ++k){
		if (L[i] <= R[j]){ 
			A[k] = L[i];
			i++;
		}
		else{
			A[k] = R[j];
			j++;
		}
	}
	delete []L;
	delete []R;
}


void merge_sort(int* A, int p, int r){
	if (p < r){
		int q = (p + r) / 2;
		merge_sort(A, p, q);
		merge_sort(A, q + 1 , r);
		merge(A, p, q, r);
	}
}


int main()
{
	int A[] = { 9, 15, 13};
	merge_sort(A, 0, 2);
	for (int i = 0; i != 3; ++i)
		cout << A[i] << " ";
	cout << endl;
	return 0;
}

2.3习题选做
2.3.2重写过程MERGE,使之不使用哨兵,而是一旦数组L或R的所有元素均被复制回A就立即停止。
不带哨兵的 MERGE伪代码
MERGE(A, p, q, r)
1   n1 = q - p + 1
2   n2 = r - q
3   let L[0 .. n1-1] and R[ .. n2-1] be new arrays
4   for i = 1 to n1 - 1
5       L[i] = A[p + i - 1]
6   for j = 0 to n2 - 1
7       R[j] = A[q + j]
8   i = 0
9   j = 0
10 k = p
11 while n1!=i and n2!=j
12     if R[i] <= L[j]
13        A[k++] = R[i++]
14     else A[k++] = L[j++]
15 while i < n1
16      A[k++] = L[i++]
17 while j < n2
18      A[k++] = L[j++]

算法的c++代码实现:
#include<iostream>
using namespace std;

void merge(int* A, int p, int q, int r) {
	int n1 = q - p + 1;
	int n2 = r - q;

	int* L = new int[n1];
	int* R = new int[n2];
	for (int i = 0; i < n1; i++)
		L[i] = A[p + i];
	for (int i = 0; i < n2; i++)
		R[i] = A[q + 1 + i];

	int i = 0, j = 0, k = p;
	while (i < n1 && j < n2) {
		if (L[i] <= R[j])
			A[k++] = L[i++];
		else 
			A[k++] = R[j++];
	}

	while (i < n1) {
		A[k++] = L[i++];
	}
	while (j < n2) {
		A[k++] = R[j++];
	}

	delete[] R;
	delete[] L;
}

void merge_sort(int* A, int p, int r){
	if (p < r){
		int q = (p + r) / 2;
		merge_sort(A, p, q);
		merge_sort(A, q + 1, r);
		merge(A, p, q, r);
	}
}

int main()
{
	int A[] = { 13, 12, 11, 19, 18, 90, 54, 89, 76 };
	merge_sort(A, 0, 8);
	for (int i = 0; i != 9; i++)
		cout << A[i] << " ";
	cout << endl;
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值