这里写目录标题
多路查找树
2-3树
插入28
B树 B+树 B*树
图
快速入门案例
代码实现
package com.luyi.graph;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author 卢意
* @create 2020-12-16 19:12
*/
public class Graph {
private ArrayList<String> vertexList; // 存储节点的集合
private int[][] edges; // 存储对应的邻接矩阵
private int numberOfEdges; // 表示边的数目
public static void main(String[] args) {
// 节点的个数
int n = 5;
String[] vertexValue = {
"A", "B", "C", "D", "E"};
// 创建图对象
Graph graph = new Graph(n);
// 循环添加节点数据
for (String item : vertexValue) {
graph.insertVertex(item);
}
// 添加边 A-B A-C B-C B-D B-E
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.showGraph();
}
public Graph (int n) {
// 初始化矩阵 和 arrayList
edges = new int[n][n];
vertexList = new ArrayList<>(n);
numberOfEdges = 0;
}
// 图的常用方法
// 1 返回节点的个数
public int getNumberOfVertex() {
return vertexList.size();
}
// 2 得到边的数目
public int getNumberOfEdges() {
return numberOfEdges;
}
// 3 返回节点i(下标) 对应的数据 0->"A" 1->"B"
public String getValueByIndex(int i) {
return vertexList.get(i);
}
// 4. 返回v1 和 v2 边的权值
public int insertVertex(int v1, int v2) {
return edges[v1][v2];
}
// 5. 显示图对应的矩阵
public void showGraph() {
System.out.println("遍历矩阵 ");
for (int[] k : edges) {
System.out.println(Arrays.toString(k));
}
}
// 插入节点
public void insertVertex(String vertex) {
vertexList.add(vertex);
}
// 添加边
/**
*
* @param v1 第一个顶点的下标 第几个顶点
* @param v2 第二个顶点的下标
* @param weight 边的权值
*/
public void insertEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numberOfEdges++;
}
}
图的深度优先遍历
代码实现
package com.luyi.graph;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author 卢意
* @create 2020-12-16 19:12
*/
public class Graph {
private ArrayList<String> vertexList; // 存储节点的集合
private int[][] edges; // 存储对应的邻接矩阵
private int numberOfEdges; // 表示边的数目
private boolean[] isVisited; // 记录节点是否被访问
public static void main(String[] args) {
// 节点的个数
int n = 5;
String[] vertexValue = {
"A", "B", "C", "D", "E"};
// 创建图对象
Graph graph = new Graph(n);
// 循环添加节点数据
for (String item : vertexValue) {
graph.insertVertex(item);
}
// 添加边 A-B A-C B-C B-D B-E
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.showGraph();
System.out.println("深度优先遍历");
graph.dfs(); // A->B->C->D->E->
}
public Graph (int n) {
// 初始化矩阵 和 arrayList
edges = new int[n][n];
vertexList = new ArrayList<>(n);
numberOfEdges = 0;
isVisited = new boolean[n];
}
// 得到第一个邻接结点的下标
/**
* 求该结点的第一个邻接矩阵下标
* @param index 该结点的下标
* @return 如果存在就返回对应的下标 否则返回-1
*/
public int getFirstNeighbor(int index) {
for (int j = 0; j < vertexList.size(); j++) {
if (edges[index][j] > 0) {
return j;
}
}
return -1;
}
// 根据前一个邻接节点的下标 获取下一个邻接节点
public int getNextNeighbor(int v1, int v2) {
for (int j = v2 + 1; j < vertexList.size(); j++) {
if (edges[v1][j] > 0) {
return j;
}
}
return -1;
}
// 深度优先遍历方法
public void dfs(boolean[] isVisit, int i) {
// 首先访问该节点
System.out.print(getValueByIndex(i) + "->");
// 将该节点设置已经访问过
isVisit[i] = true;
// 查找下标为i 的邻接节点
int w = getFirstNeighbor(i);
while (w != -1) {
if (!isVisit[w]) {
// 没有被访问过
dfs(isVisit, w);
}
// 如果w 被访问过了 去找 下标为i 的节点的 下一个邻接节点的下一个邻接节点
w = getNextNeighbor(i, w);
}
}
// 对dfs 进行重载 遍历所有的节点 并进行 dfs
public void dfs() {
// 回溯遍历dfs
for(int i = 0; i < vertexList.size(); i++) {
if (!isVisited[i]) {
dfs(isVisited, i);
}
}
}
// 图的常用方法
// 1 返回节点的个数
public int getNumberOfVertex() {
return vertexList.size();
}
// 2 得到边的数目
public int getNumberOfEdges() {
return numberOfEdges;
}
// 3 返回节点i(下标) 对应的数据 0->"A" 1->"B"
public String getValueByIndex(int i) {
return vertexList.get(i);
}
// 4. 返回v1 和 v2 边的权值
public int insertVertex(int v1, int v2) {
return edges[v1][v2];
}
// 5. 显示图对应的矩阵
public void showGraph() {
System.out.println("遍历矩阵 ");
for (int[] k : edges) {
System.out.println(Arrays.toString(k));
}
}
// 插入节点
public void insertVertex(String vertex) {
vertexList.add(vertex);
}
// 添加边
/**
*
* @param v1 第一个顶点的下标 第几个顶点
* @param v2 第二个顶点的下标
* @param weight 边的权值
*/
public void insertEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numberOfEdges++;
}
}
图的广度优先遍历
代码实现
// 对一个结点进行广度优先遍历的方法
private void bfs(boolean[] isVisited, int i) {
int u; // 表示队列的头结点的下标
int w; // 邻接节点的下标
// 队列存放访问过的节点 (现进先出)
LinkedList<Integer> queue = new LinkedList<Integer>();
// 访问当前节点
System.out.print(getValueByIndex(i) + "->");
// 标记为已访问
isVisited[i] = true;
// 将节点加入队列
queue.addLast(i);
while (!queue.isEmpty()) {
// 取出对列的头结点坐标
u = queue.removeFirst();
w = getFirstNeighbor(u);
while (w != -1) {
//
// 是否访问过
if (!isVisited[w]) {
System.out.print(getValueByIndex(w) + "->");
isVisited[w] = true;
// 入队列
queue.addLast(w);
}
// 已经访问过的话 以u为为前驱 找 w 的下一个邻接结点
w = getNextNeighbor(u, w); // 体现出广度优先
}
}
}
// 遍历所有的节点 都进行广度优先搜索
public void bfs() {
for (int i = 0; i < vertexList.size(); i++) {
if (!isVisited[i]) {
bfs(isVisited, i);
}
}
}
图的深度优先 VS 广度优先
程序员常用10种算法
二分查找法 非递归
代码实现
package com.luyi.algorithm;
/**
* @author 卢意
* @create 2020-12-17 14:26
*/
public class BinarySearchNoRecursion {
public static void main(String[] args) {
//
int[] arr = {
1,3, 8, 10, 11, 67, 100};
int i = binarySearch(arr, 100);
System.out.println(i);
}
/**
* 二分查找的非递归实现
* @param arr 带查找的数组 arr 默认是升序排列
* @param target 要查找的目标
* @return -1 表示没有找到
*/
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (arr[mid] == target) {
return mid;
}else if (arr[mid] > target) {
// 需要向左边查找
right = mid - 1;
}else {
// 需要向右边查找
left = mid + 1;
}
}
return -1;
}
}
分治算法
分治法解决汉诺塔问题 代码实现
package com.luyi.algorithm;
/**
* 汉罗塔 移动的方案 分治算法
* @author 卢意
* @create 2020-12-17 15:02
*/
public class DACHanoiTower {
public static void main(String[] args) {
hanoiTower(64, 'A', 'B', 'C');
}
/**
*
* @param num 要移动的个数
* @param a 起始位置
* @param b 中转位置
* @param c 目标位置
*/
public static void hanoiTower(int num, char a, char b, char c) {
// 如果只有一个盘
if (num == 1) {
System.out.println("第1个盘从" + a + "->" + c);
} else {
// 如果我们有n >= 2情况 我们总是可以看做是两个盘 1 最下面的盘 2 上面所有的盘
// 1 先把上面的盘 a - > b 移动过程暂存到c
hanoiTower(num- 1, a, c, b