▶ 书中第六章部分程序,包括在加上自己补充的代码,B-树

● B-树

 package package01;

 import edu.princeton.cs.algs4.StdOut;

 public class class01<Key extends Comparable<Key>, Value>
{
private static final int M = 4; // 子节点数量为 M-1 private Node root; // 根节点
private int height; // 树高
private int n; // 键值对的数量 private static final class Node // 节点类
{
private int m; // 当前子节点数量
private Entry[] children = new Entry[M]; // 子节点列表 private Node(int k) // 构造有 k 个子节点的节点
{
m = k;
}
} private static class Entry // 子节点列表类,内部结点使用 key 和 next,外部节点使用 key 和 value
{
private Comparable key;
private Node next;
private final Object val; public Entry(Comparable inputKey, Object inputVal, Node inputNext)
{
key = inputKey;
next = inputNext;
val = inputVal;
}
} public class01()
{
root = new Node(0);
} public int size()
{
return n;
} public boolean isEmpty()
{
return size() == 0;
} public int height()
{
return height;
} public Value get(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<get> key == null.\n");
return search(root, key, height);
} private Value search(Node x, Key key, int ht) // 穿如数奉告,每次进入更深层时减一
{
Entry[] children = x.children;
if (ht == 0) // 到达的是叶节点,遍历列表
{
for (int j = 0; j < x.m; j++)
{
if (eq(key, children[j].key)) // 找到了,返回 val
return (Value)children[j].val;
}
}
else // 到达的是内部节点
{
for (int j = 0; j < x.m; j++)
{
if (j == x.m - 1 || less(key, children[j + 1].key)) // j 到达最后或找到合适的子节点,进入下一层
return search(children[j].next, key, ht - 1);
}
}
return null;
} public void put(Key key, Value val)
{
if (key == null)
throw new IllegalArgumentException("\n<put> key == null.\n");
Node u = insert(root, key, val, height); // 执行插入插座并调整总键值对数量
n++;
if (u == null) // 没有需要调整的节点
return;
Node t = new Node(2); // 根节点需要分裂,新建一个具有 2 个子节点的节点
t.children[0] = new Entry(root.children[0].key, null, root); // 第一个子节点是原来的根节点
t.children[1] = new Entry(u.children[0].key, null, u); // 第二个子节点是插入操作导致新增加的节点
root = t; // root 编程新建的 t,并增加一层树高
height++;
} private Node insert(Node h, Key key, Value val, int ht)
{
int j;
Entry t = new Entry(key, val, null);
if (ht == 0) // 到达的是外部节点
{
for (j = 0; j < h.m; j++)
{
if (less(key, h.children[j].key)) // 找到合适的位置就脱出循环
break;
}
}
else // 到达的是内部节点
{
for (j = 0; j < h.m; j++)
{
if ((j + 1 == h.m) || less(key, h.children[j + 1].key)) // j 到达最后或找到合适的子节点,进入下一层
{
Node u = insert(h.children[j++].next, key, val, ht - 1);// 在 h.children[j] 进行插入
if (u == null)
return null;
t.key = u.children[0].key; // 把 u 的信息改造到 t 上
t.next = u; // 真正 next 是在这里赋值的,指向下一个子节点
break;
}
}
}
for (int i = h.m; i > j; i--) // 调整本层,排在插入位置之后的元素都向后移动一格
h.children[i] = h.children[i - 1];
h.children[j] = t; // 插入节点 t,增加 h 的子节点数量
h.m++;
return (h.m < M) ? null : split(h); // 节点 h 满了就需要扩容,返回扩容后多出来的节点,用于上一层调整
} private Node split(Node h) // 分裂节点 h,并返回分裂出来的后一半节点
{
Node t = new Node(M / 2);
h.m = M / 2; // 改 h 的子节点数为一半,相当于废弃后一半记录
for (int j = 0; j < M / 2; j++) // 后一半元素搬进 t
t.children[j] = h.children[M / 2 + j];
return t;
} public String toString()
{
return toStringKernel(root, height, "") + "\n";
} private String toStringKernel(Node h, int ht, String indent) // 遍历树转化为字符串
{
StringBuilder s = new StringBuilder();
Entry[] children = h.children;
if (ht == 0) // 叶节点,输出
{
for (int j = 0; j < h.m; j++)
s.append(indent + children[j].key + " " + children[j].val + "\n"); // 注意换行
}
else // 非叶节点,遍历子节点列表
{
for (int j = 0; j < h.m; j++)
{
if (j > 0)
s.append(indent + "(" + children[j].key + ")\n");
s.append(toStringKernel(children[j].next, ht - 1, indent + " "));
}
}
return s.toString();
} private boolean less(Comparable k1, Comparable k2)
{
return k1.compareTo(k2) < 0;
} private boolean eq(Comparable k1, Comparable k2)
{
return k1.compareTo(k2) == 0;
} public static void main(String[] args) // 输入一堆网站和 IP 建立 B-树
{
class01<String, String> st = new class01<String, String>(); st.put("www.cs.princeton.edu", "128.112.136.12");
st.put("www.cs.princeton.edu", "128.112.136.11");
st.put("www.princeton.edu", "128.112.128.15");
st.put("www.yale.edu", "130.132.143.21");
st.put("www.simpsons.com", "209.052.165.60");
st.put("www.apple.com", "17.112.152.32");
st.put("www.amazon.com", "207.171.182.16");
st.put("www.ebay.com", "66.135.192.87");
st.put("www.cnn.com", "64.236.16.20");
st.put("www.google.com", "216.239.41.99");
st.put("www.nytimes.com", "199.239.136.200");
st.put("www.microsoft.com", "207.126.99.140");
st.put("www.dell.com", "143.166.224.230");
st.put("www.slashdot.org", "66.35.250.151");
st.put("www.espn.com", "199.181.135.201");
st.put("www.weather.com", "63.111.66.11");
st.put("www.yahoo.com", "216.109.118.65"); StdOut.println("cs.princeton.edu: " + st.get("www.cs.princeton.edu"));
StdOut.println("hardvardsucks.com: " + st.get("www.harvardsucks.com"));
StdOut.println("simpsons.com: " + st.get("www.simpsons.com"));
StdOut.println("apple.com: " + st.get("www.apple.com"));
StdOut.println("ebay.com: " + st.get("www.ebay.com"));
StdOut.println("dell.com: " + st.get("www.dell.com"));
StdOut.println(); StdOut.println("size: " + st.size());
StdOut.println("height: " + st.height());
StdOut.println(st);
StdOut.println();
}
}

● 测试函输出,即生成的树

cs.princeton.edu:  128.112.136.12
hardvardsucks.com: null
simpsons.com: 209.052.165.60
apple.com: 17.112.152.32
ebay.com: 66.135.192.87
dell.com: 143.166.224.230 size: 17
height: 2
www.amazon.com 207.171.182.16
www.apple.com 17.112.152.32
www.cnn.com 64.236.16.20
(www.cs.princeton.edu)
www.cs.princeton.edu 128.112.136.12
www.cs.princeton.edu 128.112.136.11
www.dell.com 143.166.224.230
(www.ebay.com)
www.ebay.com 66.135.192.87
www.espn.com 199.181.135.201
www.google.com 216.239.41.99
(www.microsoft.com)
www.microsoft.com 207.126.99.140
www.nytimes.com 199.239.136.200
(www.princeton.edu)
www.princeton.edu 128.112.128.15
www.simpsons.com 209.052.165.60
(www.slashdot.org)
www.slashdot.org 66.35.250.151
www.weather.com 63.111.66.11
(www.yahoo.com)
www.yahoo.com 216.109.118.65
www.yale.edu 130.132.143.21

《算法》第六章部分程序 part 2的更多相关文章

  1. 《算法》第六章部分程序 part 7

    ▶ 书中第六章部分程序,加上自己补充的代码,包括全局最小切分 Stoer-Wagner 算法,最小权值二分图匹配 ● 全局最小切分 Stoer-Wagner 算法 package package01; ...

  2. 《算法》第六章部分程序 part 6

    ▶ 书中第六章部分程序,包括在加上自己补充的代码,包括二分图最大匹配(最小顶点覆盖)的交替路径算法和 HopcroftKarp 算法 ● 二分图最大匹配(最小顶点覆盖)的交替路径算法 package ...

  3. 《算法》第六章部分程序 part 5

    ▶ 书中第六章部分程序,包括在加上自己补充的代码,网络最大流 Ford - Fulkerson 算法,以及用到的流量边类和剩余流量网络类 ● 网络最大流 Ford - Fulkerson 算法 pac ...

  4. 《算法》第六章部分程序 part 8

    ▶ 书中第六章部分程序,加上自己补充的代码,包括单纯形法求解线性规划问题 ● 单纯形法求解线性规划问题 // 表上作业法,I 为单位阵,y 为对偶变量,z 为目标函数值 // n m 1 // ┌── ...

  5. 《算法》第六章部分程序 part 4

    ▶ 书中第六章部分程序,包括在加上自己补充的代码,利用后缀树查找最长重复子串.查找最大重复子串并输出其上下文(Key word in context,KWIC).求两字符串的最长公共子串 ● 利用后缀 ...

  6. 《算法》第六章部分程序 part 3

    ▶ 书中第六章部分程序,包括在加上自己补充的代码,后缀树的两种实现 ● 后缀树实现一 package package01; import java.util.Arrays; import edu.pr ...

  7. 《算法》第六章部分程序 part 1

    ▶ 书中第六章部分程序,包括在加上自己补充的代码,粒子碰撞系统及用到的粒子类 ● 粒子系统 package package01; import java.awt.Color; import edu.p ...

  8. 《算法》第一章部分程序 part 1

    ▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...

  9. 《算法》第二章部分程序 part 5

    ▶ 书中第二章部分程序,加上自己补充的代码,包括利用优先队列进行多路归并和堆排序 ● 利用优先队列进行多路归并 package package01; import edu.princeton.cs.a ...

随机推荐

  1. KMP(字符串匹配)算法

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  2. 关于MySql悲观锁与乐观锁

    悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念.本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍. 悲观锁(Pessimistic Lock) 悲观锁的 ...

  3. 查AIX 版本和系统参数

    查AIX版本 atii:[/home/pmts]oslevel -s 7100-01-07-1316 即AIX 7.1版本atii:[/home/pmts]lsdev -C 查CPU个数 (逻辑数目) ...

  4. C++进阶--静态初始化的惨败

    /* Initialization Fiasco 一个会使程序崩溃的细微的问题 */ // 不同文件的编译顺序是不确定的 // 如果一个文件依赖另一个文件的对象先初始化,可能出现问题 // 解决方法: ...

  5. bzoj5008: 方师傅的房子

    Description 方师傅来到了一个二维平面.他站在原点上,觉得这里风景不错,就建了一个房子.这个房子是n个点的凸多边形 ,原点一定严格在凸多边形内部.有m个人也到了这个二维平面.现在你得到了m个 ...

  6. mac nginx 一些资料

    http://www.jianshu.com/p/918eb337a206 mac 的nginx 配置目录在/usr/local/etc/nginx 安装之前最好执行brew的update和upgra ...

  7. [VS2013]发布网站时修改配置文件

    本文来自:https://msdn.microsoft.com/en-us/library/ee942158.aspx#encrypt_webconfig Web Deployment FAQ for ...

  8. Oracle下PLSQL连接没有数据库的问题

    https://blog.csdn.net/master_yao/article/details/51055850 参考博文地址 当PLSQL连接提示时请注意 请将首选项里内容进行修改 指定oci.d ...

  9. Scrapy学习篇(四)之数据存储

    上一篇中,我们简单的实现了toscrapy网页信息的爬取,并存储到mongo,本篇文章信息看看数据的存储.这一篇主要是实现信息的存储,我们以将信息保存到文件和mongo数据库为例,学习数据的存储,依然 ...

  10. HDFS的工作流程

    HDFS的工作机制 概述 HDFS集群分为两大角色:NameNode.DataNode NameNode负责管理整个文件系统的元数据 DataNode 负责管理用户的文件数据块 文件会按照固定的大小( ...