- 从今天开始学习算法导论这本书,将自己的学习内容记录下来。
2.1 插入排序(9页)
// 下面是伪代码,参数A为一个无序的数组,调用INSERTION-SORT方法后,使无序数组A变成有序数组(升序)
INSERTION-SORT(A)
for j = 2 to A.length
key = A[j]
// Insert A[j] into the sorted sequence A[1...j-1].
i = j-1;
while i>0 and A[i]>key
A[i+1] = A[i]
i = i-1
A[i+1] = key
// 下面是JS的代码
function insertion_sort(A) { // 从数组下标为1开始,与之它前面的所有下标一一比较
for (var j = 1; j < A.length; j++) { // 因为伪代码是从1开始的,而数组是从0开始的,所以这里的j=1
var key = A[j]; // 定义一个临时变量,存储当前A[j]的值
var i = j - 1; // i = j的前一个数
while (i >= 0 & A[i] > key) { // 让key与A[i]比较,如果A[i]的数大,进入循环,将当前A[i]的值放在下一个下标的位置
A[i + 1] = A[i];
i = i - 1; // 使 i=i-1,直到不满足条件,跳出循环。
}
A[i + 1] = key; // 循环最后一次的i的位置就是i+1,因为在循环结束时,i=i-1,所以需要i+1,A[i+1]=key
}
}
var A = [1,2,3,6,2,4,5,7];
insertion_sort(A);
console.log(A); // [ 1, 2, 2, 3, 4, 5, 6, 7 ]
2.3 分治法(17页)
// 伪代码,参数A是一个数组,参数p是子数组下标第一组有序序列开始的位置,参数q是子数组下标第一组有序序列下标结束的位置,参数r是第二组有序序列下标结束的位置,A的子数组9~16下标包含序列(2,4,5,7,1,2,3,6),调用MERGE(A,9,12,16),结果为A中的子数组9~16下标是一个有序的序列(1, 2, 2, 3, 4, 5, 6, 7 )
MERGE(A, p, q, r)
n1 = q - p + 1
n2 = r - q
let L[1..n1+1] and R[1..n2+1] be new arrays
for i = 1 to n1
L[i] = A[p+i-1]
for j = 1 to n2
R[j] = A[q+j]
L[n1+1] = ∞
R[n2+1] = ∞
i = 1
j = 1
for k = p to r
if L[i] <= R[j]
A[k] = L[i]
i = i + 1
else A[k] = R[j]
j = j + 1
// 下面是js的代码
function merge(A, p, q, r) {
n1 = q - p + 1;
n2 = r - q;
var L = new Array(n1);
var R = new Array(n2);
for (i = 0; i < n1; i++) {
L[i] = A[p + i];
}
for (j = 0; j < n2; j++) {
R[j] = A[q + j + 1];
}
L[n1] = Number.POSITIVE_INFINITY;
R[n2] = Number.POSITIVE_INFINITY;
i = 0;
j = 0;
for (k = p; k <= r; k++) {
if (L[i] <= R[j]) {
A[k] = L[i];
i = i + 1;
} else if (A[k] = R[j]) {
A[k] = R[j];
j = j + 1;
}
}
}
var A = [1,2,3,6,2,4,5,7];
merge(A, 0, 3, 7);
console.log(A); // [ 1, 2, 2, 3, 4, 5, 6, 7 ]
4.1 最大子数组问题(40页)
// 伪代码,返回一个下标数组划定跨越中点的最大子数组的边界,并返回最大子数组中值的和。
FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)
left-sum = -∞ // 保存目前为止找到的最大和
sum = 0 // 保存A[i...mid]中所有值的和
for i = mid downto low
sum = sum+A[i]
if sum > left-sum
left-sum = sum
max-left = i
right-sum = -∞
sum = 0
for j = mid + 1 to high
sum = sum + A[j]
if sum > right -sum
right-sum = sum
max-right = j
return (max-left, max-right, left-sum + right-sum)
// 下面是js代码
function find_max_crossing_subarray(A, low, mid, high) {
var left_sum = Number.NEGATIVE_INFINITY;
var sum1 = 0;
var max_left;
for (var i = mid; i >= low; i--) {
sum1 = sum1 + A[i];
if (sum1 > left_sum) {
left_sum = sum1;
max_left = i;
}
}
var right_sum = Number.NEGATIVE_INFINITY;
var sum2 = 0;
var max_right;
for (var j = mid + 1; j <= high; j++) {
sum2 = sum2 + A[j];
if (sum2 > right_sum) {
right_sum = sum2;
max_right = j
}
}
return [max_left, max_right, left_sum + right_sum]
}
var A = [13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7];
console.log(find_max_crossing_subarray(A, 0, A.length / 2, A.length - 1)); // [ 7, 10, 43 ]
4.1 最大子数组问题_分治算法(41)
// 伪代码,在FIND-MAX-CROSSING-SUBARRAY()方法的基础上实现
FIND-MAXIMUM-SUBARRAY(A, low, high)
if high == low
return (low, high, A[low])
else mid = {(low+high)/2}
(left-low, left-high, left-sum) =
FIND-MAXIMUM-SUBARRAY(A, low, mid)
(right-low, right-high, right-sum) =
FIND-MAXIMUM-SUBARRAY(A, mid+1, high)
(cross-low, cross-high, cross-sum) =
FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)
if left-sum >= right-sum and left-sum >= cross-sum
return (left-low, left-high, left-sum)
elseif rightr-sum >= left-sum and right-sum >= cross-sum
return (right-low, right-high, right-sum)
else return (cross-low, cross-high, cross-sum)
// 下面是js代码
function find_maximum_subarray(A, low, high) {
// left_set[0]是left-low, left_set[1]是left-high, left_set[2]是left-sum
// right_set[0]是right-low, right_set[1]是left-high, right_set[2]是right-sum
// cross_set[0]是cross-low, cross_set[1]是cross-high, cross_set[2]是cross-sum
var left_set = [];
var right_set = [];
var cross_set = [];
if (high == low) {
return [low, high, A[low]];
} else {
var mid = parseInt((low + high) / 2);
left_set = find_maximum_subarray(A, low, mid);
right_set = find_maximum_subarray(A, mid + 1, high);
cross_set = find_max_crossing_subarray(A, low, mid, high);
if (left_set[2] >= right_set[2] & left_set[2] >= cross_set[2]) {
return [left_set[0], left_set[1], left_set[2]];
} else if (right_set[2] >= left_set[2] & right_set[2] >= cross_set[2]) {
return [right_set[0], right_set[1], right_set[2]];
} else {
return [cross_set[0], cross_set[1], cross_set[2]];
}
}
}
console.log(find_maximum_subarray(A, 0, A.length)); // [ 7, 10, 43 ]
未完待更新…