算法导论的伪代码使用JS的实现

  • 从今天开始学习算法导论这本书,将自己的学习内容记录下来。

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 ]

未完待更新…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值