导论阅读笔记

12 二叉搜索树

package algo;

import java.util.LinkedList;
import java.util.Queue;

public class BisTree {

    public static BisTreeNode root ;

    public static class BisTreeNode{
        public int val;
        BisTreeNode left;
        BisTreeNode right;
        BisTreeNode p;
        public BisTreeNode(int val){
            this.val = val;
        }
    }



    public static void process(BisTreeNode r){
        System.out.print(r.val+",");
    }

    //中序遍历
    public static void inorderWalk(BisTreeNode r){
        if(r!=null){
            inorderWalk(r.left);
            process(r);
            inorderWalk(r.right);
        }
    }

    //查询递归
    public static BisTreeNode search1(BisTreeNode r,int value){
        if(r==null||r.val==value)return r;
        if(value>r.val)return search1(r.right,value);
        else return search1(r.left,value);
    }

    //查询迭代
    public static BisTreeNode search2(BisTreeNode r,int value){
        while(r!=null&&r.val!=value){
            if(value>r.val)r=r.right;
            r = r.left;
        }
        return r;
    }

    //最大关键字
    public static BisTreeNode maximum(BisTreeNode r){
        while(r!=null&&r.right!=null){
            r = r.right;
        }
        return r;
    }

    //最小关键字
    public static BisTreeNode minimum(BisTreeNode r){
        while(r!=null&&r.left!=null){
            r=r.left;
        }
        return r;
    }

    //后继
    public static BisTreeNode successor(BisTreeNode r){
        if(r.right!= null)
            return minimum(r.right);
        BisTreeNode y = r.p;
        while(y!=null&&r==y.right){
            r= y;
            y=y.p;
        }
        return y;
    }

    //前驱
    public static BisTreeNode predecessor(BisTreeNode r){
        if(r.left!=null)
            return maximum(r.left);
        BisTreeNode y = r.p;
        while(y!=null&&r==y.left){
            r=y;
            y=y.p;
        }
        return y;
    }

    //插入
    public static BisTreeNode insert(BisTreeNode r,BisTreeNode x){
        BisTreeNode y = null;
        while(r!=null){
            y = r;
            if(x.val>r.val)r=r.right;
            else r = r.left;
        }
        x.p= y;
        if(y==null) root = x;
        else if(x.val>y.val)y.right = x;
        else y.left = x;
        return x;
    }

    public static void transplant(BisTreeNode u,BisTreeNode v){
        if(u.p==null)root = v;
        else if (u== u.p.left)u.p.left = v;
        else u.p.right = v;
        v.p = u.p;
    }

    //删除
    public static void delete(BisTreeNode r,BisTreeNode x){
        if(x.left==null) transplant(x,x.right);
        else if(x.right==null)transplant(x,x.left);
        else {
            //先找它的后继,用后继来替换它的位置,
            // 用后继的右子树替换后继
            BisTreeNode y = minimum(x.right);
            if(y.p!=x){
                //x的后继不是它的右子树,那么需要用y的右子树替换y
                transplant(y,y.right);
                y.right = x.right;
                y.right.p = y.p;
            }
            //x的后继就是y的右子树,y肯定没有左子树,
            transplant(x,y);
            y.left = x.left;
            y.left.p = y;

        }
    }

    public static void printTree(BisTreeNode r){
        Queue<BisTreeNode> q = new LinkedList<>();
        q.add(r);
        while(!q.isEmpty()){
            BisTreeNode t = q.poll();
            if(t!=null){
                System.out.print(t.val+",");
                if(t.left!=null)q.offer(t.left);
                if(t.right!=null)q.offer(t.right);
            }
        }
    }



    public static void main(String[] args) {
        BisTreeNode t1 = new BisTreeNode(12);
        BisTreeNode t2 = new BisTreeNode(5);
        BisTreeNode t3 = new BisTreeNode(18);
        BisTreeNode t4 = new BisTreeNode(2);
        BisTreeNode t5 = new BisTreeNode(9);
        BisTreeNode t6 = new BisTreeNode(15);
        BisTreeNode t7 = new BisTreeNode(19);
        BisTreeNode t8 = new BisTreeNode(13);
        BisTreeNode t9 = new BisTreeNode(17);
        root = t1;
        insert(root,t2);
        insert(root,t3);
        insert(root,t4);
        insert(root,t5);
        insert(root,t6);
        insert(root,t7);
//        insert(root,t8);
        insert(root,t9);
        printTree(root);
        System.out.println();
        //刪除前
        delete(root,t1);
        printTree(root);
    }

}

13 红黑树

红黑树插入删除详解 https://blog.csdn.net/li1914309758/article/details/80997342

package algo;

import java.util.LinkedList;
import java.util.Queue;

public class BRTree {

    public static BRTreeNode nil = new BRTreeNode();

    public static BRTreeNode root;

    //红黑树宇宙铁律
    //1.每个结点是红色的或者黑色的
    //2.根节点是黑色的
    //3.每个叶节点(nil)是黑色的
    //4.如果一个结点是红色的,那么它的两个子节点都是黑色的
    //5.对每个结点,从该结点到其所有后代的简单路径上,均包含相同数目的黑色结点

    //左卷化, 卷都可以卷
    public static void leftRotate(BRTreeNode x) {
        //           x                    y
        //          / \                  / \
        //         a   y       ->       x   c
        //            / \              / \
        //           b   c            a   b

        //           1                    3
        //          / \                  / \
        //         2   3       ->       1   5
        //            / \              / \
        //           4   5            2   4

        BRTreeNode y = x.right;
        //y.left link to x
        x.right = y.left;
        if (y.left != nil) y.left.p = x;
        //y.p link to x.p
        y.p = x.p;
        if (x.p == nil) root = y;            //x为根节点
        else if (x == x.p.left) x.p.left = y; //父节点的左子树
        else x.p.right = y;                 //父节点的右子树
        //x link to y.left
        y.left = x;
        x.p = y;
    }

    //右卷化, 卷都可以卷
    public static void rightRotate(BRTreeNode y) {
        //           x                    y
        //          / \                  / \
        //         a   y       <-       x   c
        //            / \              / \
        //           b   c            a   b


        BRTreeNode x = y.left;
        //link x.right = y.left;
        y.left = x.right;
        if (y.left != nil) x.left.p = y;

        //x.p to y.p
        if (y.p == nil) root = x;
        else if (y == y.p.left) y.p.left = x;
        else y.p.right = x;

        //y to x.right
        x.right = y;
        y.p = x;
    }

    //新同学加入
    public static void insert(BRTreeNode z) {
        BRTreeNode x = root;
        BRTreeNode y = nil;
        while (x != nil) {
            y = x;
            if (z.val > x.val) x = x.left;
            else x = x.right;
        }
        //连到x的爸爸上
        z.p = y;
        if (y == nil) root = z;
        else if (z.val > y.val) y.right = z;
        else y.left = z;
        //新节点为红色
        z.left = nil;
        z.right = nil;
        z.color = 1;
        insertFixup(z);
    }

    //从下往上修复对红黑树铁律的破坏
    public static void insertFixup(BRTreeNode z) {
        //已知 z是红色的,看它爸爸
        //如果 z是根节点 z.p肯定是黑色,进不了循环
        while (z.p.color == 1) {

            if (z.p == z.p.p.left)//它爸是左子树
            {
                //          11,0
                //          /   \
                //        2,1    14,0
                //       /   \       \
                //     1,0  7,0      15,1
                //          / \
                //        5,1  8,1 <-y
                //        /
                //  z-> 4,1
                BRTreeNode y = z.p.p.right;//它叔
                if (y.color == 1) { //case 1 变色
                    z.p.color = 0;
                    y.color = 0;
                    z.p.p.color = 1;
                    z = z.p.p;
                }
                //          11,0                             11,0
                //          /   \                            /  \
                //        2,1    14,0 <-y                  7,1  14,0 <-y
                //       /   \       \                    /  \    \
                //     1,0  7,1 <-z    15,1         z-> 2,1  8,0  15,1
                //          / \                        /  \
                //        5,0  8,0                  1,0   5,0
                //        /                               /
                //      4,1                              4,1
                else {
                    if (z == z.p.right) {      //case2 左旋它爸
                        z = z.p;
                        leftRotate(z);
                    }
                    //            11,0                             7,0
                    //            /  \                           /     \
                    //           7,1  14,0 <-y             z-> 2,1      11,1
                    //          /  \    \                      / \       /  \
                    //    z-> 2,1  8,0  15,1                 1,0 5,0   8,0  14,0 <-y
                    //       /  \                            /
                    //      1,0   5,0                      4,1
                    //     /
                    //   4,1
                    else {                      //case3 着色并右旋
                        z.p.color = 0;
                        z.p.p.color = 1;
                        rightRotate(z.p.p);
                    }
                }
            } else {   //它爸是右子树
                //          11,0
                //          /   \
                //        2,1    14,0
                //       /   \       \
                //     1,0  7,0      15,1
                //          / \
                //  y->   5,1  8,1
                //               \
                //                4,1 <-z
                BRTreeNode y = z.p.p.left;//它左叔
                if (y.color == 1) {
                    z.p.color = 0;
                    y.color = 0;
                    z.p.p.color = 1;
                    z = z.p.p;
                } else {
                    //          11,0                             11,0
                    //          /   \                            /  \
                    //        2,1    14,0 <-y                  7,1  14,0 <-y
                    //       /   \       \                    /  \    \
                    //     1,0  7,1 <-z    15,1         z-> 2,1  8,0  15,1
                    //          / \                        /  \
                    //        5,0  8,0                  1,0   5,0
                    //        /                               /
                    //      4,1                              4,1
                    //          11,0
                    //          /  \
                    //     y->14,0 2,1
                    //
                    // 右旋它爸
                    if (z == z.p.left) {
                        z = z.p;
                        rightRotate(z);
                    }
                    z.p.color = 0;
                    z.p.p.color = 1;
                    leftRotate(z.p.p);
                }
            }
        }
    }

    //移植
    public static void transplant(BRTreeNode u, BRTreeNode v) {
        if (u.p == nil) {//如果u是根
            root = v;
        } else if (u == u.p.left) u.p.left = v;
        else u.p.right = v;
        v.p = u.p;
    }

    public static BRTreeNode minimum(BRTreeNode t) {
        BRTreeNode y = nil;
        while (t != nil) {
            y = t;
            t = t.left;
        }
        return y;
    }

    public static BRTreeNode maximum(BRTreeNode t) {
        BRTreeNode y = nil;
        while (t != nil) {
            y = t;
            t = t.right;
        }
        return y;
    }

    public static BRTreeNode predecessor(BRTreeNode t) {
        if (t.left != nil) return maximum(t.left);
        BRTreeNode y = t.p;
        while (y != nil && t == y.left) {
            t = y;
            y = y.p;
        }
        return y;
    }

    public static BRTreeNode successor(BRTreeNode t) {
        if (t.right != nil) return minimum(t.right);
        BRTreeNode y = t.p;
        while (y != nil && t == y.right) {
            t = y;
            y = y.p;
        }
        return y;
    }


    public static void delete(BRTreeNode z) {
        BRTreeNode y = z;
        BRTreeNode x;
        int yOrignalColor = y.color;
        // 1. 始终维持y为从树中删除的结点或者移至树内的结点
        // 2. 始终保持x为替换z的节点
        if (z.left == nil) {
            x = z.right;
            transplant(z, x);
        } else if (z.right == nil) {
            x = z.left;
            transplant(z, x);
        } else {
            //y是z的后继
            y = minimum(z.right);
            yOrignalColor = y.color;
            x = y.right;
            // y 没有左子树
            // y是z的右子树,这个时候直接替换就行
            if (y.p == z) {
                x.p = y;
            } else {
                //y不是z的右子树
                transplant(y, y.right);
                y.right = z.right;
                y.right.p = y;
            }
            transplant(z, y);
            y.left = z.left;
            y.left.p = y;
            y.color = z.color;
        }
        if (yOrignalColor == 0) {
            deleteFixUp(x);
        }
    }

    public static void deleteFixUp(BRTreeNode x) {
        BRTreeNode w;//始终指向x的sibling
        //只有x为黑色才会破坏红黑属性
        while (x != root && x.color == 0) {
            if (x == x.p.left) {
                // x是左子树
                w = x.p.right;
                if (w.color == 1) {
                    //case1
                    //        b,0
                    //       /   \
                    //  x->a,0   d,1 <-w
                    //           / \
                    //         c,0 e,0
                    //
                    //         |
                    //         v
                    //
                    //        d,0
                    //       /   \
                    //     b,1   e,0
                    //     / \
                    //x->a,0  c,0 <-w
                    w.color = 0;
                    x.p.color = 1;
                    leftRotate(w);
                    w = x.p.right;
                }
                //case2
                //        b,1
                //       /   \
                //  x->a,0   d,0 <-w
                //           / \
                //         c,0 e,0
                //
                //         |
                //         v
                //
                //   x->  b,0
                //       /   \
                //     a,0   d,1
                //           / \
                //         c,0 e,0
                if (w.left.color == 0 && w.right.color == 0) {
                    w.color = 1;
                    x = x.p;
                } else {
                    if (w.right.color == 0) {
                        //case 3
                        //        b,1
                        //       /   \
                        //  x->a,0   d,0 <-w
                        //           / \
                        //         c,1 e,0
                        //
                        //         |
                        //         v
                        //
                        //        b,1
                        //       /   \
                        //  x->a,0   c,0 <-w
                        //             \
                        //             d,1
                        //               \
                        //               e,0
                        w.color = 1;
                        w.left.color = 0;
                        rightRotate(w);
                        w = x.p.right;
                    }
                    //case 4
                    //        b,0/1
                    //       /   \
                    //  x->a,0   d,0 <-w
                    //           / \
                    //         c,0/1 e,1
                    //
                    //         |
                    //         v
                    //
                    //        d,0/1
                    //       /   \
                    //     b,0    e,1
                    //    /   \
                    //x->b,0  c,0/1
                    w.color = x.p.color;
                    x.p.color = 0;
                    leftRotate(w);
                    x = root;//目的是终止循环
                }
            } else {
                // x是右子树
                w = x.p.left;
                if (w.color == 1) {
                    //如果w是红的那么其父节点只能是黑的
                    //case 1
                    //       d,0
                    //       / \
                    // w-> b,1  e,0 <-x
                    //    /   \
                    //  a,0   c,0
                    //
                    //      |
                    //      V
                    //
                    //
                    //       b,0
                    //       / \
                    //     a,0  d,1
                    //          /  \
                    //    w-> c,0  e,0<-x
                    w.color = 0;
                    x.p.color = 0;
                    rightRotate(w);
                    w = x.p.left;
                }
                //w为黑的三种情况
                //case2
                //       d,1/0
                //       / \
                // w-> b,0  e,0 <-x
                //    /   \
                //  a,0   c,0
                //
                //      |
                //      V
                //
                //
                //       d,1/0 <-x
                //       / \
                //     b,1  e,0
                //    /   \
                //  a,0   c,0
                if (w.left.color == 0 && w.right.color == 0) {
                    w.color = 1;
                    x = x.p;
                } else {
                    if (w.left.color == 0) {
                        //case3
                        //       d,1/0
                        //       / \
                        // w-> b,0  e,0 <-x
                        //    /   \
                        //  a,0   c,1
                        //
                        //      |
                        //      V
                        //
                        //       d,1
                        //       / \
                        // w-> c,0  e,0 <-x
                        //    /
                        //  b,1
                        //  /
                        //a,0
                        w.color = 1;
                        w.right.color = 0;
                        leftRotate(w);
                        w = x.p.left;
                    }
                    //case4
                    //       d,1/0
                    //       / \
                    // w-> b,0  e,0 <-x
                    //    /   \
                    //  a,1   c,1
                    //
                    //      |
                    //      V
                    //
                    //       b,1/0
                    //       / \
                    //     a,0  d,0
                    //         /   \
                    //       c,1   e,0
                    w.color = x.p.color;
                    x.p.color = 0;
                    w.left.color = 0;
                    rightRotate(x.p);
                    //跳出循环
                    x = root;
                }
            }


        }
        x.color = 0;
    }

    public static void printTree(BRTreeNode r) {
        Queue<BRTreeNode> q = new LinkedList<>();
        q.add(r);
        while (!q.isEmpty()) {
            BRTreeNode t = q.poll();
            if (t != nil) {
                System.out.print(t.val + ",");
                if (t.left != nil) q.offer(t.left);
                if (t.right != nil) q.offer(t.right);
            }
        }
    }


    public static void main(String[] args) {
//        BRTreeNode t1 = new BRTreeNode(1,0,nil,nil,nil);
//        BRTreeNode t2 = new BRTreeNode(2,0,nil,nil,nil);
//        BRTreeNode t3 = new BRTreeNode(3,0,nil,nil,nil);
//        BRTreeNode t4 = new BRTreeNode(4,0,nil,nil,nil);
//        BRTreeNode t5 = new BRTreeNode(5,0,nil,nil,nil);
//        root = t1;
//        t1.left = t2;t2.p=t1;
//        t1.right =t3;t3.p=t1;
//        t3.left = t4;t4.p=t3;
//        t3.right = t5;t5.p = t3;
//
//        printTree(root);
//        System.out.println();
//
//        leftRotate(root);
//
//        printTree(root);
//        System.out.println();
//
//        rightRotate(root);
//        printTree(root);
//
//        BRTreeNode a1 = new BRTreeNode(11, 0, nil, nil, nil);
//        BRTreeNode a2 = new BRTreeNode(2, 1, nil, nil, nil);
//        BRTreeNode a3 = new BRTreeNode(14, 0, nil, nil, nil);
//        BRTreeNode a4 = new BRTreeNode(1, 0, nil, nil, nil);
//        BRTreeNode a5 = new BRTreeNode(7, 0, nil, nil, nil);
//        BRTreeNode a6 = new BRTreeNode(15, 1, nil, nil, nil);
//        BRTreeNode a7 = new BRTreeNode(5, 1, nil, nil, nil);
//        BRTreeNode a8 = new BRTreeNode(8, 1, nil, nil, nil);
//        BRTreeNode a9 = new BRTreeNode(4, 1, nil, nil, nil);
//
//        root = a1;
//        a1.left = a2;
//        a2.p = a1;
//        a1.right = a3;
//        a3.p = a1;
//        a2.left = a4;
//        a4.p = a2;
//        a2.right = a5;
//        a5.p = a2;
//        a3.right = a6;
//        a6.p = a3;
//        a5.left = a7;
//        a7.p = a5;
//        a5.right = a8;
//        a8.p = a5;
//        a7.left = a9;
//        a9.p = a7;
//
//        printTree(root);
//        System.out.println();
//        insertFixup(a9);
//        printTree(root);

        BRTreeNode d1 = new BRTreeNode(9, 0, nil, nil, nil);
        BRTreeNode d2 = new BRTreeNode(4, 0, nil, nil, nil);
        BRTreeNode d3 = new BRTreeNode(14, 0, nil, nil, nil);
        BRTreeNode d4 = new BRTreeNode(1, 1, nil, nil, nil);
        BRTreeNode d5 = new BRTreeNode(6, 1, nil, nil, nil);
        BRTreeNode d6 = new BRTreeNode(12, 1, nil, nil, nil);
        BRTreeNode d7 = new BRTreeNode(18, 1, nil, nil, nil);
        BRTreeNode d8 = new BRTreeNode(0, 0, nil, nil, nil);
        BRTreeNode d9 = new BRTreeNode(2, 0, nil, nil, nil);
        BRTreeNode d10 = new BRTreeNode(5, 0, nil, nil, nil);
        BRTreeNode d11 = new BRTreeNode(7, 0, nil, nil, nil);
        BRTreeNode d12 = new BRTreeNode(11, 0, nil, nil, nil);
        BRTreeNode d13 = new BRTreeNode(13, 0, nil, nil, nil);
        BRTreeNode d14 = new BRTreeNode(16, 0, nil, nil, nil);
        BRTreeNode d15 = new BRTreeNode(19, 0, nil, nil, nil);
        BRTreeNode d16 = new BRTreeNode(3, 1, nil, nil, nil);
        BRTreeNode d17 = new BRTreeNode(8, 1, nil, nil, nil);
        BRTreeNode d18 = new BRTreeNode(10, 1, nil, nil, nil);
        BRTreeNode d19 = new BRTreeNode(15, 1, nil, nil, nil);
        BRTreeNode d20 = new BRTreeNode(17, 1, nil, nil, nil);
//        d1.left = d2;d1.right = d3;d2.p = d1;d3.p = d1;
//        d2.left = d4;d2.right = d5;d4.p = d2;d5.p = d2;
//        d3.left = d6;d3.right = d7;d6.p = d3;d7.p = d3;
//        d4.left = d8;d4.right = d9;d8.p = d4;d9.p = d4;
        root = d1;
        link(d1,d2,d3);
        link(d2,d4,d5);
        link(d3,d6,d7);
        link(d4,d8,d9);
        link(d5,d10,d11);
        link(d6,d12,d13);
        link(d7,d14,d15);
        link(d9,nil,d16);
        link(d11,nil,d17);
        link(d12,d18,nil);
        link(d14,d19,d20);

        printTree(root);
        delete(d6);
        System.out.println();
        printTree(root);
        System.out.println();
        delete(d4);
        printTree(root);
        System.out.println();
        delete(d1);
        printTree(root);
    }

    public static void link(BRTreeNode t,BRTreeNode left,BRTreeNode right){
        t.left = left;
        t.right = right;
        left.p =t;
        right.p = t;
    }


}

15 动态规划

我们通常按照如下4个步骤来设计一个动态规划算法:
1.刻画一个最优解的结构特征
2.递归地定义最优解地值
3.计算最优解的值,通常采用自底向上的方法
4.利用计算的信息构造一个最优解

15.1 切钢管问题

package algo;

public class Dp {

    //对应长度钢管的价格
    public static int[] p={0,1,5,8,9,10,17,17,20,24,30};

    //自顶向下递归的求解
    public static int cutRod(int n){
        if(n==0)return 0;
        int q = Integer.MIN_VALUE;
        for(int i=1;i<=n;i++){
            q = Math.max(q,p[i]+cutRod(n-i));
        }
        return q;
    }
    public static int[] r;

    //自顶向下填记录式
    public static void initR(int n){
        r = new int[n+1];
        for(int i=0;i<=n;i++)r[i]=Integer.MIN_VALUE;
    }
    public static int cutRod2(int n){
        if(r[n]>=0)return r[n];
        if(n==0)return 0;
        int q = Integer.MIN_VALUE;
        for(int i=1;i<=n;i++){
            q = Math.max(p[i],cutRod2(n-i));
        }
        r[n]=q;
        return q;
    }

    //自底向上 动态规划
    public static int cutRod3(int n){
        r = new int[n+1];
        for(int j=1;j<=n;j++){
            int q = Integer.MIN_VALUE;
            for(int i=1;i<=j;i++){
                q = Math.max(q,p[i]+r[j-i]);
            }
            r[j]=q;
        }
        return r[n];
    }
    //重构解法保存切割方案


    public static int cutRod4(int n){
        r = new int[n+1];
        int[]  s = new int[n+1];
        for(int i=1;i<=n;i++){
            int q = Integer.MIN_VALUE;
            for(int j=1;j<=i;j++){
//                q = Math.max(q,p[j]+r[i-j]);
                if(q<p[j]+r[i-j]){
                    q = p[j]+r[i-j];
                    s[i]=j;
                }
            }
            r[i]=q;
        }
        for(int i=0;i<=n;i++){
            System.out.println("i="+i+",s[i]="+s[i]);
        }
        return r[n];
    }

    public static void main(String[] args) {
        //解法1
        long startTime = System.currentTimeMillis();
        System.out.println("n=10:"+cutRod(10));
        System.out.println(System.currentTimeMillis()-startTime);
        //解法2
        startTime = System.currentTimeMillis();
        initR(10);
        System.out.println("n=10:"+cutRod2(10));
        System.out.println(System.currentTimeMillis()-startTime);
        //解法3
        startTime = System.currentTimeMillis();
        System.out.println("n=10:"+cutRod3(10));
        System.out.println(System.currentTimeMillis()-startTime);
        //
        startTime = System.currentTimeMillis();
        System.out.println("n=10:"+cutRod4(7));
        System.out.println(System.currentTimeMillis()-startTime);
    }
}

15.2 矩阵链问题

package algo;

import utils.ArrayUtils;

public class Matrix {

    public static int[][] m;
    public static int[][] s;

    //矩阵链
    public static int matrixChainOrder(int[] p) {
        int n = p.length-1;
        m = new int[n + 1][n + 1];
        s = new int[n + 1][n + 1];
        for (int i = 1; i <= n; i++) {
            m[i][i] = 0;
        }
        for (int l = 2; l <= n; l++) {
            for (int i = 1; i <= n - l + 1; i++) {
                int j = i + l - 1;
                m[i][j] = Integer.MAX_VALUE;
                for (int k = i; k <= j - 1; k++) {
                    int q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
                    if (q < m[i][j]) {
                        m[i][j] = q;
                        s[i][j] = k;
                    }
                }
            }
        }
        return m[1][n];
    }

    //打印括号
    public static void print(int[][] s,int i,int j){
        if(i==j){
            System.out.print("A"+i);
        }
        else{
            System.out.print("(");
            print(s,i,s[i][j]);
            print(s,s[i][j]+1 ,j);
            System.out.print(")");
        }
    }



    public static void main(String[] args) {
        int[] p = {30, 35, 15, 5, 10, 20, 25};
        System.out.println(matrixChainOrder(p));
        ArrayUtils.printMatrix(m);

        ArrayUtils.printMatrix(s);

        print(s,1,p.length-1);
    }
}

15.3动态规划原理

  • 无权最短路径具有最优子问题结构
  • 无权最长路径不具有最优子问题结构
  1. 子问题无关性质
  2. 重叠子问题

15.4 LCS 最长公共子序列问题

package algo;

import utils.ArrayUtils;

public class LCS {
    public static int[][] c;
    public static char[][] b;

    public static int lcsLong(char[] x, char[] y) {
        int m = x.length;
        int n = y.length;
        c = new int[m + 1][n + 1];
        b = new char[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            c[i][0] = 0;
        }
        for (int j = 1; j <= n; j++) {
            c[0][j] = 0;
        }
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (x[i - 1] == y[j - 1]) {
                    c[i][j] = c[i - 1][j - 1] + 1;
                    b[i][j] = '↖';
                } else if (c[i - 1][j] >= c[i][j - 1]) {
                    c[i][j] = c[i - 1][j];
                    b[i][j] = '↑';
                } else {
                    c[i][j] = c[i][j - 1];
                    b[i][j] = '←';
                }
            }
        }
        return c[m][n];
    }

    //打印最长公共子串
    public static void printLcs(char[] x,int i,int j){
        if(i==0||j==0) return;
        if(b[i][j]=='↖') {
            printLcs(x,i-1,j-1);
            System.out.print(x[i-1]);
        }
        else if(b[i][j]=='↑'){
            printLcs(x,i-1,j);
        }
        else{
            printLcs(x,i,j-1);
        }
    }

    public static void main(String[] args) {
        char[] x = {'A', 'B', 'C', 'B', 'D', 'A', 'B' };
        char[] y = {'B', 'D', 'C', 'A', 'B', 'A' };
        System.out.println(lcsLong(x, y));
        ArrayUtils.printMatrix(c);
        ArrayUtils.printMatrix(b);
        printLcs(x,x.length,y.length);
    }
}

15.5 最优二叉搜索树

package algo.ita;


import util.ArrayUtil;

public class ObsTree {

    //最优二叉搜索树期望代价
    static double[][] e;
    //从i到j的所有概率值和
    static double[][] w;
    //保存根节点的下标记
    static int[][] root;

   

    public static void optimal(double[] p, double[] q, int n) {
        e = new double[n + 2][n + 2];
        w = new double[n + 2][n + 2];
        root = new int[n + 2][n + 2];

        for (int i = 1; i <= n + 1; i++) {
            e[i][i - 1] = q[i - 1];
            w[i][i - 1] = q[i - 1];
        }

        for (int l = 1; l <= n; l++) {
            for (int i = 1; i <= n - l + 1; i++) {
                int j = i + l - 1;
                e[i][j] = Double.MAX_VALUE;
                w[i][j] = w[i][j - 1] + p[j] + q[j];
                for (int r = i; r <= j; r++) {
                    double t = e[i][r - 1] + e[r + 1][j] + w[i][j];
                    if (t < e[i][j]) {
                        e[i][j] = t;
                        root[i][j] = r;
                    }
                }
            }
        }

    }


    public static void main(String[] args) {
        double[] q = {0.05, 0.10, 0.05, 0.05, 0.05, 0.10};
        double[] p = {0, 0.15, 0.10, 0.05, 0.10, 0.20};

        optimal(p, q, q.length-1);
        ArrayUtil.printMatrix(e);
        ArrayUtil.printMatrix(w);
        ArrayUtil.printMatrix(root);
    }
}

16 贪心算法

16.1 活动选择问题

package algo;

import utils.ArrayUtils;

public class greedy {

    public static int[] a = new int[10];
    public static int c = 0;

    //假定s,f中的元素已经按照结束顺序排列好

    //递归法
    public static void greedyR(int[] s, int[] f,int k ,int n){
        int m = k+1;
        while(m<=n&&s[m]<f[k])m++;
        if(m<=n){
            a[c++]=m;
            greedyR(s,f,m,n);
        }
    }

    //迭代法 尾递归->迭代
    public static void greedy(int[] s,int[] f){
        int n = s.length-1;
        a[c++]=1;
        int k = 1;
        for(int m =2;m<=n;m++){
            if(s[m]>=f[k]){
                a[c++]=m;
                k = m;
            }
        }
        ArrayUtils.printArray(a);
    }


    public static void main(String[] args) {
        int[] s = {0,1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12};
        int[] f = {0,4, 5, 6, 7, 9, 9, 10, 11, 12, 14, 16};

        //递归法
//        greedyR(s,f,0,s.length-1);
//        ArrayUtils.printArray(a);

        greedy(s,f);
    }
}

16.2 贪心算法原理

贪心选择性质 局部最优解->全局最优解

最优子结构

贪心vs 动态规划

  • 0-1 背包问题与分数背包问题

16.3 赫夫曼编码

17 摊还分析

17.1 聚合分析

17.2 核算法

17.3 势能法

17.4 动态表

18 B树

18.2B书上的基本操作

以沿树单程下行的方式向B树插入关键字

B-TREE-INSERT(T,k)
  r = T.root
  if r.n = 2t-1
    s = ALLOCATE-NOTE()
    T.root = s
    s.leaf = FALSE
    s.n = 0
    s.c1 = r
    B-TREE-SPLIT-CHILD(s,1)
    B-TREE-INSERT-NONFULL(s,k)
  else B-TREE-INSERT-NONFULL(s,k)

B-TREE-INSERT-NONFULL(x,k)
  i = x.n
  if x.leaf
   while i >=1 and k<x.key(i)
    x.key(i+1)= x.key(i)
    i = i-1
   x.key(i+1)= k
   x.n = x.n+1
   DISK-WRITE(x)
  else while i>=1 and k <x.key(i)
        i=i-1
       i= i+1
       DISK-READ(x,ci)
       if x.ci.n == 2t-1
        B-TREE-SPLIT-CHILD(x,i)//有意思按照k来分裂结点,并不是中间节点
        if k> x.key(i)
          i = i+1
       B-TREE-INSERT-NONFULL(x.ci,k)  

18.3 从B树中删除关键字

B-TREE-DELETE从以x为根的子树中删除关键字k。这个过程必须保证无论何时,结点x递归调用自身时,x中关键字个数至少为最小度数t。


posted @ 2021-03-04 09:49  Fake_coder  阅读(75)  评论(0编辑  收藏  举报