《算法》第六章部分程序 part 2
▶ 书中第六章部分程序,包括在加上自己补充的代码,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的更多相关文章
- 《算法》第六章部分程序 part 7
▶ 书中第六章部分程序,加上自己补充的代码,包括全局最小切分 Stoer-Wagner 算法,最小权值二分图匹配 ● 全局最小切分 Stoer-Wagner 算法 package package01; ...
- 《算法》第六章部分程序 part 6
▶ 书中第六章部分程序,包括在加上自己补充的代码,包括二分图最大匹配(最小顶点覆盖)的交替路径算法和 HopcroftKarp 算法 ● 二分图最大匹配(最小顶点覆盖)的交替路径算法 package ...
- 《算法》第六章部分程序 part 5
▶ 书中第六章部分程序,包括在加上自己补充的代码,网络最大流 Ford - Fulkerson 算法,以及用到的流量边类和剩余流量网络类 ● 网络最大流 Ford - Fulkerson 算法 pac ...
- 《算法》第六章部分程序 part 8
▶ 书中第六章部分程序,加上自己补充的代码,包括单纯形法求解线性规划问题 ● 单纯形法求解线性规划问题 // 表上作业法,I 为单位阵,y 为对偶变量,z 为目标函数值 // n m 1 // ┌── ...
- 《算法》第六章部分程序 part 4
▶ 书中第六章部分程序,包括在加上自己补充的代码,利用后缀树查找最长重复子串.查找最大重复子串并输出其上下文(Key word in context,KWIC).求两字符串的最长公共子串 ● 利用后缀 ...
- 《算法》第六章部分程序 part 3
▶ 书中第六章部分程序,包括在加上自己补充的代码,后缀树的两种实现 ● 后缀树实现一 package package01; import java.util.Arrays; import edu.pr ...
- 《算法》第六章部分程序 part 1
▶ 书中第六章部分程序,包括在加上自己补充的代码,粒子碰撞系统及用到的粒子类 ● 粒子系统 package package01; import java.awt.Color; import edu.p ...
- 《算法》第一章部分程序 part 1
▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...
- 《算法》第二章部分程序 part 5
▶ 书中第二章部分程序,加上自己补充的代码,包括利用优先队列进行多路归并和堆排序 ● 利用优先队列进行多路归并 package package01; import edu.princeton.cs.a ...
随机推荐
- paramiko 实现ssh登录和sftp登录
简单ssh登录 import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddP ...
- 黄聪:初识Pjax:pjax是什么
听说博主不再折腾wordpress了,陌小雨还是转载到网站做个备份吧,万一哪天没有了呢.陌小雨觉得讲的挺清楚的,小白都能懂. pjax是 pushstate + ajax,分别百度可以得到相关资料,在 ...
- 黄聪:C#如何使用fiddlercoreCapture监控手机APP
1.去下载Fiddler:https://www.telerik.com/download/fiddler 2.安装Fiddler,按下图所示导出证书,导出后在桌面得到:FiddlerRoot.cer ...
- vi 编辑器基本命令
命令模式(esc) k 上移一行j 下移一行h 左移一行l 右移一行 6j 下移6行 5k 上移5行 0 将游标放在一行的开始$ 将游标放在一行的末尾w 将游标移动到下一个单词b 将游标移动到上一个 ...
- JS一行代码,生成一个16进制随机颜色,简单粗暴。
var color = '#'+ Math.random().toString(16).substr(-6); document.body.style.backgroundColor = color; ...
- [Java]JGit用法总结
clone public static void gitClone(String remoteUrl, File repoDir) { try { Git git = Git.cloneReposit ...
- PyQt—QTableWidget实现翻页功能
主要使用QTableWidget中的三个函数实现: verticalScrollBar().setSliderPosition() 设置当前滑动条的位置 verticalScrollBar().max ...
- bzoj5007: TCP协议
Description 在如今的网络中,TCP是一种被广泛使用的网络协议,它在传输层提供了可靠的通信服务.众所周知,网络是存在 时延的,例如用户先后向服务器发送了两个指令op1和op2,并且希望服务器 ...
- ES6基础三(对象)
对象赋值 在es6中,可以直接将声明的变量赋值给对象: Object.keys().Object.values()和Object.entries() 在ES6中,允许我们使用变量作为对象的ke ...
- UnicodeString基本操作(Ring3)
// Unicode_String_Ring3.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "Unicode ...