导论阅读笔记
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动态规划原理
- 无权最短路径具有最优子问题结构
- 无权最长路径不具有最优子问题结构
- 子问题无关性质
- 重叠子问题
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。
I'm a fucKing fake coder!