《算法导论》个人笔记(一)

今天的笔记是第一部分:基础知识中的第1、2章内容。先来个概述,第一章主要介绍算法是什么,算法在计算中能起到什么作用。第二章主要介绍算法基础,讲了一个插入排序算法,同时介绍了如何分析算法的复杂度,还引入了分治法的思想,归并排序算法。另,包含一些练习题。
一、算法
  1. 算法是什么
        算法就是任何定义良好的计算过程,它取一个或一组值作为输入,并产生出一个或一组值作为输出。也就是说,算法就是一系列的计算过程,用来将输入的数据转换成输出结果。
        例如:我们需要把一个数列按照非递减排序。下面是关于排序问题的形式定义。
        输入:n个数的一个序列{a1,a2,a3,a4,…,an}。
       输出:输入序列的一个排列{a1’,a2’,a3’,a4’,…,an’},满足a1’<= a2’ <= a3’ … <= an’。
  2. 算法的应用
  3. 以上咱们使用算法解决排序问题,但是算法实际应用无处不在。例如:
    • 分析数据库中存储的人类基因工程中30亿个化学基对的序列
    • 管理和处理互联网上的海量数据,访问与检索大量信息
    • 电子商务对个人订单信息保密,核心技术是公钥密码和数字签名
二、算法基础
1、插入排序法
  • 插入排序是一个对少量元素进行排序的有效算法。
    我们将其伪代码过程命名为INSERTION-SORT,它的参数是一个数组A[1 .. n],包含了n个待排数字。
    (在伪代码中,A中元素的个数n用A.length来表示)
    算法思想:每趟将一个元素,按照其中元素的大小插入到它前面已经排序的子序列中,依此重复,直到插入全部元素。
        **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
    
  • 插入排序算法的简单Java实现
     
       /**
         * 插入排序
         *
         * @param array
         */
        public static void insertionSort(int[] array) {
            int key, j;
            for (int i = 1; i < array.length; i++) {
                key = array[i];
                j = i - 1;
                while (j >= 0 && array[j] > key) {
                    array[j + 1] = array[j];
                    j--;
                }
                array[j + 1] = key;
            }
        }
    
  • 算法分析

        算法分析是指对一个算法所需要的资源进行预测。内存,通信带宽或计算机硬件等资源偶尔会是我们主要关心的,但通常,资源是指我们希望度量的是计算时间。
        我们就不把插入排序算法的分析过程一一贴出来了,插入排序算法的时间复杂度是T(n)=O(n*n)。

2、分治思想
  • 将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题。然后再合并这些子问题的解来建立原问题的解。
    分治模式在每层l递归时都有三个步骤:
    • 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
    • 解决这些子问题,递归地求解各个子问题。然而,若子问题的规模足够小,则直接求解。
    • 合并这些子问题的解成原问题的解。
  • 归并排序算法
    归并排序算法完全遵循分治模式。 直观上操作如下:
    • 分解:将 n 个元素分成各含 n / 2个元素的子序列;
    • 解决:用归并排序法对两个子序列递归地排序;
    • 合并:合并两个已排序的子序列以得到排序结果。
        对子序列排序时,其长度为1时递归”开始回升”。在这种情况下不要做任何工作,因为长度为1的每个序列都已排好序。归并排序的关键步骤在于合并两个已排序的子序列。
        这里引入一个辅助过程MERGE(A, p, q, r),其中A为数组,p,q和r都是下标,有p <= q < r。该过程假设子数组A[p .. q]和A[q+1 .. r]都已排好序,并将它们合并成一个已排好序的子数组代替当前子数组A[p .. r]。
  • 归并排序算法的实现
    合并步骤:
    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] = MAX
       R[n2 + 1] = MAX
       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
    
    排序步骤:
        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] = MAX
        R[n2 + 1] = MAX
        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
    
  • 归并排序算法Java实现
        /**
        * 归并排序
        *
        * @param array
        */
        public static void mergeSort(int[] array) {
            mergeSort(array, 0, array.length - 1);
        }
    
        private static void mergeSort(int[] array, int p, int r) {
            int q;
            if (p < r) {
                q = (p + r) >> 1;
                mergeSort(array, p, q);
                mergeSort(array, q + 1, r);
                merge(array, p, q, r);
            }
        }
    
        private static void merge(int[] array, int p, int q, int r) {
            int lLen = q - p + 1;
            int rLen = r - q;
            int[] left = new int[lLen + 1];
            int[] right = new int[rLen + 1];
            int i, j;
            for (i = 0; i < lLen; i++)
                left[i] = array[p + i];
            for (j = 0; j < rLen; j++)
                right[j] = array[q + j + 1];
            left[i] = Integer.MAX_VALUE;
            right[j] = Integer.MAX_VALUE;
            i = j = 0;
            for (int k = p; k <= r; k++) {
                if (left[i] <= right[j])
                    array[k] = left[i++];
                else
                    array[k] = right[j++];
            }
        }
    
习题
  1. 插入排序改写成递归过程
    INSERTION-SORT-RECURSIVE(A, p)
        if p > 1
            key = A[p]
            p = p - 1
            INSERTION-SORT-RECURSIVE(A, p)
            INSERTION-ELEMENT(A, p, key)
    
    INSERTION-ELEMENT(A, p, key)
        while p > 0 and A[p] > key
            A[p + 1] = A[p]
            p = p - 1
        A[p + 1] = key
    
  2. 二分查找伪码
    **BINARY-SEARCH(A, v)**
        front = 1
        end = A.length
        while front < end
            middle = (front + end) / 2
            if A[middle] < v
                front = middle + 1
            else if A[middle] > v
                end = middle - 1
            else
                return middle
        return -1
    
  3. 设计算法:查找集合S中是否存在两个元素和等于x的元素。
    思路:先排序,后查找
    **CHECK-SUM(S, x)**
        A = MERGE-SORT(S)
        for i = 1 to A.length
            v = x - A[i]
            if BINARY-SEARCH(A, v) > 0
                return true
        return false
    
感谢大家花时间阅读本人博客,在接下来每周会更新一篇算法导论的算法设计博文。当中有什么问题还请大家指正,相互学习,相互促进!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值