java数据结构复习02
1.递归问题
1.1计算阶乘
package interview.recursion;
import java.util.Scanner;
public class Fact {
public static void main(String[] args) {
System.out.println("请输入n的值:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int num = fact(n);
System.out.println(n + "的阶乘为:" + num);
}
public static int fact(int n) {
if (n == 1) {
return 1;
}
return n * fact(n - 1);
}
}

1.2计算斐波那契数列
Fibonacci sequence:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ……
package interview.recursion;
import java.util.Scanner;
public class Fib {
public static int fib(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}
public static void main(String[] args) {
System.out.println("请输入n的值:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int num = fib(n);
System.out.println("第" + n + "个值的fib为:" + +num);
}
}

1.3计算最大公约数(辗转相除法)



package interview.recursion;
import java.util.Scanner;
public class Gcd {
public static int gcd(int max, int min) {
if (min == 0) {
return max;
} else {
return gcd(min, max % min);
}
}
public static void main(String[] args) {
System.out.println("请输入max的值:");
Scanner in = new Scanner(System.in);
int max = in.nextInt();
System.out.println("请输入min的值:");
int min = in.nextInt();
int num = gcd(max, min);
System.out.println(max + "和" + min + "的最大公约数为:" + num);
}
}

1.4汉诺塔问题(递归)
问题描述
三个柱子,起初有若干个按大小关系顺序安放的盘子,需要全部移动到另外一个柱子上。移动规则:在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
移动次数: f(n)=2n -1
解法思路
使用递归算法进行处理。
(1)把a上的n-1个盘通过c移动到b。
(2)把a上的最下面的盘移到c。
(3)因为n-1个盘全在b上了,所以把b当做a重复以上步骤就好了。
在网上找到一个3阶的汉诺塔递归过程示意图,参考一下。

package cn.jxufe.ch06_hanoitowers;
public class HanoiTowers {
/**
* 汉诺塔问题:所有的盘子,刚开始都在塔座A上,要求将所有的盘子从塔座A移动到塔座C,每次只能移动一个盘子,且
* 任何盘子不能放在比自己小的盘子上。
*
* @param topN:移动的盘子数
* @param from:从哪个塔座开始
* @param inter:中间塔座
* @param to;目标塔座
*/
public static void doTower(int topN, char from, char inter, char to) {
if (topN == 1) {
System.out.println("盘子1,从" + from + "塔座到" + to + "塔座");
return;
} else {
doTower(topN - 1, from, to, inter);
System.out.println("盘子" + topN + ",从" + from + "塔座到" + to + "塔座");
doTower(topN - 1, inter, from, to);
}
}
}
package cn.jxufe.ch06_hanoitowers;
public class TestHanoiTowers {
public static void main(String[] args) {
HanoiTowers.doTower(4,'A','B','C');
}
}

1.5瓶盖问题
package test;
/*
* 描述:每 3 个可乐盖可兑换 1 瓶子可乐,求买 n 瓶可乐最终可获得的可乐瓶子数。
*/ import java.util.Scanner; public class T03 {
public static int times = 1; public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("输入购买的可乐数:"); times = 1; int j = input.nextInt();
int i = func(j); System.out.println("--------------------------");
System.out.println("总共可获得 " + i + " 瓶\n\n");
} public static int func(int i) {
if (i < 3) {
System.out.println("最终剩下 " + i + " 个瓶盖,不足以兑换");
return i;
} else {
System.out.println("第 " + times++ + " 次兑换," + "本次兑换总共有 " + i + " 个瓶盖,用 " + (i - i % 3) + " 个瓶盖换了 " + i / 3
+ " 瓶可乐,剩余 " + i % 3 + " 个瓶盖可用于下次兑换");
return ((i - i % 3) + func(i / 3 + i % 3));
}
}
}

1.6走楼梯
题目描述:
一个台阶总共有n级,如果一次可以跳1级,也可以跳2级。求总共有多少总跳法。
思路:当n大于2的时候,每次可以选择走2级也可以选择走1级,所有都有两种方案。即f(n-1)+f(n-2)
package interview.recursion;
import java.util.Scanner;
public class Stairs {
public static int solve(int n) {
if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
} else {
return solve(n - 1) + solve(n - 2);
}
}
public static void main(String[] args) {
System.out.println("请输入n的值:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int num = solve(n);
System.out.println("总共有" + num + "种走法");
}
}

2.二叉树
2.1插入和查找

package cn.jxufe.ch07_tree; /**
* 二叉树节点
*/
public class Node {
//数据项
public int data;
public String sdata;
public Node leftChild;
public Node rightChild; public Node(int data,String sdata) {
this.data = data;
this.sdata =sdata;
}
}
package cn.jxufe.ch07_tree; /**
* 二叉树
*/
public class Tree {
//根节点
public Node root; /**
* 插入节点
*/
public void insert(int value,String sdata) {
//封装节点
Node newNode = new Node(value,sdata);
//引用当前节点
Node current = root;
//引用父节点
Node parent;
//如果root为null,也就是第一次插入的节点
if (root == null) {
root = newNode;
return;
} else {
while (true) {
//父节点指向当前节点
parent = current;
//如果当前节点指向的数据,比插入的要大,则向左走
if (value < current.data) {
current = current.leftChild;
if (current == null) {
parent.leftChild = newNode;
return;
}
} else {
current = current.rightChild;
if (current == null) {
parent.rightChild = newNode;
return;
}
}
} }
} /**
* 查找节点
*/
public Node find(int value) {
//引用当前节点,从根节点开始
Node current = root;
//只要查找的值,不等于当前节点的值
while (current.data != value) {
//比较查找值,与当前节点值的大小
if (current.data > value) {
current = current.leftChild; } else {
current = current.rightChild;
}
//如果查找不到
if (current == null) {
return null;
} }
return current; } /**
* 删除节点
*/
public void delete(int value) { }
}
package cn.jxufe.ch07_tree;
public class TestTree {
public static void main(String[] args) {
Tree tree = new Tree();
tree.insert(10, "zhangsan");
tree.insert(20, "lisi");
tree.insert(3, "wangwu");
tree.insert(14, "zhaoliu");
tree.insert(76, "zhouqi");
System.out.println(tree.root.data);
System.out.println(tree.root.leftChild.data);
System.out.println(tree.root.rightChild.data);
System.out.println(tree.root.rightChild.leftChild.data);
System.out.println(tree.root.rightChild.rightChild.data);
Node node = tree.find(20);
System.out.println(node.data + "," + node.sdata);
System.out.println(node.rightChild.data + "," + node.rightChild.sdata);
}
}

2.2遍历二叉树

package cn.jxufe.ch07_tree; /**
* 二叉树节点
*/
public class Node {
//数据项
public int data;
public String sdata;
public Node leftChild;
public Node rightChild; public Node(int data,String sdata) {
this.data = data;
this.sdata =sdata;
}
}
package cn.jxufe.ch07_tree; /**
* 二叉树
*/
public class Tree {
//根节点
public Node root; /**
* 插入节点
*/
public void insert(int value, String sdata) {
//封装节点
Node newNode = new Node(value, sdata);
//引用当前节点
Node current = root;
//引用父节点
Node parent;
//如果root为null,也就是第一次插入的节点
if (root == null) {
root = newNode;
return;
} else {
while (true) {
//父节点指向当前节点
parent = current;
//如果当前节点指向的数据,比插入的要大,则向左走
if (value < current.data) {
current = current.leftChild;
if (current == null) {
parent.leftChild = newNode;
return;
}
} else {
current = current.rightChild;
if (current == null) {
parent.rightChild = newNode;
return;
}
}
} }
} /**
* 查找节点
*/
public Node find(int value) {
//引用当前节点,从根节点开始
Node current = root;
//只要查找的值,不等于当前节点的值
while (current.data != value) {
//比较查找值,与当前节点值的大小
if (current.data > value) {
current = current.leftChild; } else {
current = current.rightChild;
}
//如果查找不到
if (current == null) {
return null;
} }
return current; } /**
* 删除节点
*/
public void delete(int value) { } /**
* 前序遍历
*/
public void frontOrder(Node localNode) {
if (localNode != null) {
//访问根节点
System.out.print(localNode.data + ":" + localNode.sdata + " ");
//前序遍历左子树
frontOrder(localNode.leftChild);
//前序遍历右子树
frontOrder(localNode.rightChild);
}
} /**
* 中序遍历
*/
public void inOrder(Node localNode) {
if (localNode != null) {
//中序遍历左子树
inOrder(localNode.leftChild);
//访问根节点
System.out.print(localNode.data + "," + localNode.sdata + " ");
//中序遍历右子树
inOrder(localNode.rightChild);
}
} /**
* 后序遍历
*/
public void afterOrder(Node localNode) {
if (localNode != null) {
//后序遍历左子树
afterOrder(localNode.leftChild);
//后序遍历右子树
afterOrder(localNode.rightChild);
//访问根节点
System.out.print(localNode.data + "," + localNode.sdata + " ");
}
}
}
package cn.jxufe.ch07_tree;
public class TestTree {
public static void main(String[] args) {
Tree tree = new Tree();
tree.insert(10, "zhangsan");
tree.insert(20, "lisi");
tree.insert(3, "wangwu");
tree.insert(14, "zhaoliu");
tree.insert(76, "zhouqi");
tree.insert(13, "zhuba");
System.out.println("前序遍历:");
tree.frontOrder(tree.root);
System.out.println();
System.out.println("中序遍历:");
tree.inOrder(tree.root);
System.out.println();
System.out.println("后序遍历:");
tree.afterOrder(tree.root);
}
}

2.3删除二叉树节点

package interview;
public class Tree {
private Node root;
public void insertNode(int data, String sdata) {
Node newNode = new Node(data, sdata);
// 引用当前节点
Node current = root;
Node parent;
// 如果root为null,也就是第一次插入
if (root == null) {
root = newNode;
} else {
while (true) {
parent = current;
// 如果当前节点指向的数据,比插入的节点数据要大,则向左走
if (data < current.data) {
current = current.leftChildNode;
if (current == null) {
parent.leftChildNode = newNode;
return;
}
} else {
current = current.rightChildNode;
if (current == null) {
parent.rightChildNode = newNode;
return;
}
}
}
}
}
public Node findNode(int value) {
Node current = root;
while (current.data != value) {
if (current.data > value) {
current = current.leftChildNode;
} else {
current = current.rightChildNode;
}
if (current == null) {
return null;
}
}
return current;
}
public void fontOrder(Node root) {
if (root != null) {
System.out.println(root.data);
fontOrder(root.leftChildNode);
fontOrder(root.rightChildNode);
}
}
public Node getSuccessor(Node delNode) {
Node successor = delNode;
Node successorParent = delNode;
Node current = delNode.rightChildNode;
while (current != null) {
successorParent = successor;
successor = current;
current = current.leftChildNode;
}
if(successor != delNode.rightChildNode) {
successorParent.leftChildNode = successor.rightChildNode;
successor.rightChildNode = delNode.rightChildNode;
}
return successor;
}
public boolean deleteNode(int value) {
// 引用当前节点为根节点
Node current = root;
// 引用当前节点的父节点
Node parent = root;
// 是否为左子树
boolean isLeftchild = true;
// 查找
while (current.data != value) {
parent = current;
// 比较
if (current.data > value) {
current = current.leftChildNode;
isLeftchild = true;
} else {
current = current.rightChildNode;
isLeftchild = false;
}
if (current == null) {
return false;
}
}
// 删除
if (current.leftChildNode == null && current.rightChildNode == null) {// 1. 删除的节点为叶子节点
if (current == root) {
root = null;
} else if (isLeftchild) {// 如果它是父节点的左子节点
parent.leftChildNode = null;
} else {
parent.rightChildNode = null;
}
} else if (current.rightChildNode == null) { // 2. 该节点有一个子节点,且为左子节点
if (current == root) {
root = current.leftChildNode;
} else if (isLeftchild) {
parent.leftChildNode = current.leftChildNode;
} else {
parent.rightChildNode = current.leftChildNode;
}
} else if (current.leftChildNode == null) { // 该节点只有一个节点,且为右子节点
if (current == root) {
root = current.rightChildNode;
} else if (isLeftchild) {
parent.leftChildNode = current.rightChildNode;
} else {
parent.rightChildNode = current.rightChildNode;
}
}else {
Node successor = getSuccessor(current);// 查找中序后继节点
if(current == root) { // 以下是完成替换功能
root = successor;
}else if(isLeftchild) {
parent.leftChildNode = successor;
}else {
parent.rightChildNode = successor;
}
successor.leftChildNode = current.leftChildNode;
}
return true;
}
public static void main(String[] args) {
Tree tree = new Tree();
tree.insertNode(10, "zhangsan");
tree.insertNode(20, "lisi");
tree.insertNode(3, "wangwu");
tree.insertNode(14, "zhaoliu");
tree.insertNode(76, "zhouqi");
tree.insertNode(5, "niaho");
// System.out.println(tree.root.data);
// System.out.println(tree.root.leftChildNode.data);
// System.out.println(tree.root.rightChildNode.data);
// System.out.println(tree.root.rightChildNode.leftChildNode.data);
// System.out.println(tree.root.rightChildNode.rightChildNode.data);
// Node node = tree.findNode(20);
// System.out.println(node.data + "," + node.sdata);
// System.out.println(node.rightChildNode.data + "," +
// node.rightChildNode.sdata);
tree.fontOrder(tree.root);
tree.deleteNode(3);
System.out.println("--------------------");
tree.fontOrder(tree.root);
tree.deleteNode(20);
System.out.println("------------------------");
tree.fontOrder(tree.root);
}
}
class Node {
// 数据域
public int data;
public String sdata;
// 指针域
public Node leftChildNode;
public Node rightChildNode;
public Node(int data, String sdata) {
// TODO Auto-generated constructor stub
this.data = data;
this.sdata = sdata;
}
}
2.4根据中序和后序,求前序遍历
package exam;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
// Scanner sc = new Scanner(System.in);
// String in = sc.nextLine();
String in = "dgbaechf";
char[] inArray = in.toCharArray();
// String last = sc.nextLine();
String last = "gbdehfca";
char[] lastArray = last.toCharArray();
// System.out.println(Arrays.toString(preArray));
// System.out.println(Arrays.toString(inArray));
Node node = buildTree(inArray, lastArray);
frontOrder(node);
}
public static Node buildTree(char[] inorder, char[] postorder) {
if (inorder == null || postorder == null || inorder.length == 0 || postorder.length == 0) {
return null;
}
// 将后序遍历的最后一个节点取出为根
Node root = new Node(postorder[postorder.length - 1]);
int i = 0;// 记录中序遍历根的位置
for (; i < inorder.length; i++) {
if (postorder[postorder.length - 1] == inorder[i]) {
break;
}
}
// 构造左子树
char[] leftIn = Arrays.copyOfRange(inorder, 0, i);
char[] leftPost = Arrays.copyOfRange(postorder, 0, i);
// 构造右子树
char[] rightIn = Arrays.copyOfRange(inorder, i + 1, inorder.length);
char[] rightPost = Arrays.copyOfRange(postorder, i, postorder.length - 1);
// 左子树
root.leftChild = buildTree(leftIn, leftPost);
// 右子树
root.rightChild = buildTree(rightIn, rightPost);
return root;
}
/**
* 前序遍历
*/
public static void frontOrder(Node localNode) {
if (localNode != null) {
// 访问根节点
System.out.print(localNode.data + " ");
// 前序遍历左子树
frontOrder(localNode.leftChild);
// 前序遍历右子树
frontOrder(localNode.rightChild);
}
}
}
/**
* 二叉树节点
*/
class Node {
// 数据项
public char data;
public Node leftChild;
public Node rightChild;
public Node(char data) {
this.data = data;
}
}

2.5二叉树高度

package datastruct.t04tree; /**
* 二叉树节点
*
*/
public class Node {
public int data;
public Node leftChild;
public Node rightChild; public Node(int data) {
this.data = data;
} public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
} public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
} public static Node createNode(int data) {
Node node = new Node(data);
node.leftChild = node.rightChild = null;
return node;
} public static void setChild(Node node, Node leftChild, Node rightChild) {
node.setLeftChild(leftChild);
node.setRightChild(rightChild);
} }
package datastruct.t04tree;
public class BiTree {
public static int getTreeHeight(Node root) {
if (root == null) {
return 0;
} else {
int leftHeight = getTreeHeight(root.leftChild);
int rightHeight = getTreeHeight(root.rightChild);
return Math.max(leftHeight, rightHeight) + 1;
}
}
public static void main(String[] args) {
// 快速构建一棵二叉树
Node root = Node.createNode(1);
Node node2 = Node.createNode(2);
Node node3 = Node.createNode(3);
Node node4 = Node.createNode(4);
Node node5 = Node.createNode(5);
Node node6 = Node.createNode(6);
Node node7 = Node.createNode(7);
Node node8 = Node.createNode(8);
Node.setChild(root, node2, node3);
Node.setChild(node2, node4, node5);
Node.setChild(node3, null, node7);
Node.setChild(node4, null, node8);
Node.setChild(node5, node6, null);
// 树的高度
int height = getTreeHeight(root);
System.out.print("树的高度为:");
System.out.println(height);
}
}

2.6表达式树的输出与求值
表达式树的特征:叶节点是运算数,非叶节点一定是运算符

输入格式:
第一行给出节点的个数N,每个节点的编号为0 ~ N-1
接下来N行每行分别给出:
该节点的编号、该节点的操作数/操作符、该节点的左孩子编号、右孩子编号(-1表示NULL)
输出格式:
第一行输出该表达式树的中缀表达式,该用括号的地方需要用括号括起来。
第二行输出该表达式树的前缀表达式。
第二行输出该表达式树的后缀表达式。
第四行输出该表达式树的计算结果,保留两位小数。
样例输入:
-
+
/
- -
*
- -
- -
- -
-
- -
- -
样例输出:
(+(*(-)))-(/)
- + * - /
- * + / -
5.00
package datastruct.t04tree.exptree;
public class Node {
char data;
Node leftChild;
Node rightChild;
}
package datastruct.t04tree.exptree;
import java.util.Scanner;
public class ExpTree {
// 中缀表达式
public static void inOrder(Node root, int layer) {
if (root == null)
return;
if (root.leftChild == null && root.rightChild == null) {
// 叶结点是操作数,直接输出,不加括号
System.out.print(root.data + " ");
} else {
// 非叶节点是操作符,需加括号(第0层根节点除外)
if (layer > 0) {
System.out.print("(");
}
inOrder(root.leftChild, layer + 1);
System.out.print(root.data + " ");
inOrder(root.rightChild, layer + 1);
if (layer > 0) {
System.out.print(")");
}
}
}
// 前缀表达式
public static void preOrder(Node root) {
if (root == null)
return;
System.out.print(root.data + " ");
preOrder(root.leftChild);
preOrder(root.rightChild);
}
// 后缀表达式
public static void postOrder(Node root) {
if (root == null)
return;
postOrder(root.leftChild);
postOrder(root.rightChild);
System.out.print(root.data + " ");
}
public static double getExpTree(Node root) {
if (root == null) {
return 0;
}
if (root.leftChild == null && root.rightChild == null) {
// 叶节点,节点存放的是 操作数
return root.data - '0'; // 将字符转换成数字
}
// 非叶结点,节点存放的是 操作符
double a = getExpTree(root.leftChild);
double b = getExpTree(root.rightChild);
return cal(a, b, root.data);
}
public static double cal(double a, double b, char op) {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default:
return 0;
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入节点的个数");
int N = input.nextInt();
Node[] nodes = new Node[N];
for (int i = 0; i < N; i++) {
nodes[i] = new Node();
}
System.out.println("请输入index,data,l,r");
for (int i = 0; i < N; i++) {
int index = input.nextInt();
char data = input.next().charAt(0);
int l = input.nextInt();
int r = input.nextInt();
nodes[index].data = data;
nodes[index].leftChild = (l != -1 ? nodes[l] : null);
nodes[index].rightChild = (r != -1 ? nodes[r] : null);
}
Node root = nodes[0];
inOrder(root, 0);
System.out.println();
preOrder(root);
System.out.println();
postOrder(root);
System.out.println();
double value = getExpTree(root);
System.out.println(value);
}
}

2.7求二叉树指定节点所在层数(假设根节点的层数为1)

1.方法1
package datastruct.t04tree.layer;
class Node {
int data;
Node leftChild;
Node rightChild;
public Node(int data) {
this.data = data;
}
public void setChild(Node leftChild, Node rightChild) {
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
public class NodeLayer {
static int layer = 0;
static boolean flag = false;// flag标记可用于提前快速结束递归的执行
public static void getNodeLayer(Node root, int value) {
if (root == null)
return;
if (flag)
return;
layer++;
if (root.data == value) {
System.out.println(layer);
flag = true;
return;
}
getNodeLayer(root.leftChild, value);
getNodeLayer(root.rightChild, value);
layer--;
}
public static void main(String[] args) {
Node root = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node8 = new Node(8);
root.setChild(node2, node3);
node2.setChild(node4, node5);
node3.setChild(null, node6);
node5.setChild(node7, null);
node7.setChild(null, node8);
int value = 7;
getNodeLayer(root, value);
}
}

2.方法2
package datastruct.t04tree.layer;
class Node {
int data;
Node leftChild;
Node rightChild;
public Node(int data) {
this.data = data;
}
public void setChild(Node leftChild, Node rightChild) {
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
public class NodeLayer {
static boolean flag = false;
public static void getNodeLayer(Node root, int value, int layer) {
if (root == null)
return;
if (flag)
return;
if (root.data == value) {
System.out.println(layer);
flag = true;
return;
}
getNodeLayer(root.leftChild, value, layer + 1);
getNodeLayer(root.rightChild, value, layer + 1);
}
public static void main(String[] args) {
Node root = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node8 = new Node(8);
root.setChild(node2, node3);
node2.setChild(node4, node5);
node3.setChild(null, node6);
node5.setChild(node7, null);
node7.setChild(null, node8);
int value = 7;
getNodeLayer(root, value, 1);
}
}

2.8求某节点到根节点的路径
对于如下二叉树,节点 7 位于第 4 层,其到跟节点的路径为 1 2 5 7

package datastruct.t04tree.path;
import java.util.Stack;
class Node {
int data;
Node leftChild;
Node rightChild;
public Node(int data) {
this.data = data;
}
public void setChild(Node leftChild, Node rightChild) {
this.leftChild = leftChild;
this.rightChild = rightChild;
}
}
public class TreePath {
static Stack<Integer> path = new Stack<>();
static boolean flag = false;
public static void getNodePath(Node root, int value) {
if (root == null)
return;
if (flag)
return;
path.add(root.data);
if (root.data == value) {
for (Integer integer : path) {
System.out.print(integer + " ");
}
flag = true;
return;
}
getNodePath(root.leftChild, value);
getNodePath(root.rightChild, value);
path.pop();
}
public static void main(String[] args) {
Node root = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node8 = new Node(8);
root.setChild(node2, node3);
node2.setChild(node4, node5);
node3.setChild(null, node6);
node5.setChild(node7, null);
node7.setChild(null, node8);
int value = 7;
getNodePath(root, value);
}
}

2.9全排列问题
输出数字1~N所能组成的所有全排列

package datastruct.t04tree.permutation;
import java.util.Stack;
public class Permutation {
public static int MAXN = 10;
static boolean[] isUsed = new boolean[MAXN];
static Stack<Integer> nums = new Stack<>();
static int N;
/**
* @param index
* 表示第几层
*/
public static void DFS(int index) {
if (index >= N) {
for (Integer i : nums)
System.out.print(i + " ");
System.out.println();
return;
}
for (int i = 1; i <= N; i++) {
if (isUsed[i])
continue;
nums.push(i);
isUsed[i] = true;
DFS(index + 1);
nums.pop();
isUsed[i] = false;
}
}
public static void main(String[] args) {
N = 3;
DFS(0);// 从第0层开始搜索
}
}

3.红黑树


4.hash表

4.1直接将关键字作为索引
package ch15;
public class Info {
private int key;
private String name;
public Info(int key, String name) {
// TODO Auto-generated constructor stub
this.key = key;
this.name = name;
}
public int getKey() {
return key;
}
public void setKey(int key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package ch15;
public class HashTable {
private Info[] arr;
public HashTable() {
// TODO Auto-generated constructor stub
arr = new Info[100];
}
public HashTable(int maxSize) {
arr = new Info[maxSize];
}
public void insert(Info info) {
arr[info.getKey()] = info;
}
public Info find(int key) {
return arr[key];
}
}
package ch15;
public class TestHashTable {
public static void main(String[] args) {
HashTable hTable = new HashTable();
hTable.insert(new Info(10, "张三"));
hTable.insert(new Info(15, "李四"));
System.out.println(hTable.find(15).getName());
}
}

4.2将单词转化为索引
package ch15;
public class Info {
private String key;
private String name;
public Info(String key, String name) {
// TODO Auto-generated constructor stub
this.key = key;
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package ch15;
public class HashTable {
private Info[] arr;
public HashTable() {
// TODO Auto-generated constructor stub
arr = new Info[100];
}
public HashTable(int maxSize) {
arr = new Info[maxSize];
}
public void insert(Info info) {
arr[hashCode(info.getKey())] = info;
}
public Info find(String key) {
return arr[hashCode(key)];
}
public int hashCode(String key) {
int hashValue = 0;
for (int i = key.length() - 1; i >= 0; i--) {
int letter = key.charAt(i) - 96;
hashValue += letter;
}
return hashValue;
}
}
package ch15;
public class TestHashTable {
public static void main(String[] args) {
HashTable hTable = new HashTable();
hTable.insert(new Info("zhangsan", "张三"));
hTable.insert(new Info("lisi", "李四"));
System.out.println(hTable.find("zhangsan").getName());
}
}

以上方法也会存在一定的问题,当hashcode相同的时候。
package ch15;
public class TestHashTable {
public static void main(String[] args) {
HashTable hTable = new HashTable();
hTable.insert(new Info("abc", "张三"));
hTable.insert(new Info("bca", "李四"));
System.out.println(hTable.find("abc").getName());
System.out.println(hTable.find("bca").getName());
}
}

我们用幂函数的方式去重写hashcode
public int hashCode(String key) {
int hashValue = 0;
int pow27 = 1;
for (int i = key.length() - 1; i >= 0; i--) {
int letter = key.charAt(i) - 96;
hashValue += letter * pow27;
pow27 *= 27;
}
return hashValue;
}
package ch15;
public class TestHashTable {
public static void main(String[] args) {
HashTable hTable = new HashTable();
hTable.insert(new Info("abc", "张三"));
hTable.insert(new Info("bca", "李四"));
System.out.println(hTable.find("abc").getName());
System.out.println(hTable.find("bca").getName());
}
}

此时可以解决上面的问题,但是浪费太多内存了,因为字符串如果很长,数组容易越界或者内存溢出,因此需要进行取模运算。
public int hashCode(String key) {
BigInteger hashValue = new BigInteger("0");
BigInteger pow27 = new BigInteger("1");
for (int i = key.length() - 1; i >= 0; i--) {
int letter = key.charAt(i) - 96;
BigInteger letterB = new BigInteger(String.valueOf(letter));
hashValue = hashValue.add(letterB.multiply(pow27));
pow27 = pow27.multiply(new BigInteger(String.valueOf(27)));
}
return hashValue.mod(new BigInteger(String.valueOf(key.length()))).intValue();
}
java数据结构复习02的更多相关文章
- java数据结构复习01
1.数组 package javaDataStruct.array01; public class MyArray { private int[] arr; // 表示有效数据的长度 private ...
- Java数据结构和算法(二)顺序存储的树结构
Java数据结构和算法(二)顺序存储的树结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 二叉树也可以用数组存储,可以和完 ...
- Java数据结构和算法(五)--希尔排序和快速排序
在前面复习了三个简单排序Java数据结构和算法(三)--三大排序--冒泡.选择.插入排序,属于算法的基础,但是效率是偏低的,所以现在 学习高级排序 插入排序存在的问题: 插入排序在逻辑把数据分为两部分 ...
- Java数据结构和算法(三)--三大排序--冒泡、选择、插入排序
三大排序在我们刚开始学习编程的时候就接触过,也是刚开始工作笔试会遇到的,后续也会学习希尔.快速排序,这里顺便复习一下 冒泡排序: 步骤: 1.从首位开始,比较首位和右边的索引 2.如果当前位置比右边的 ...
- 《Java基础复习》—常识与入门
突然发现自己Java基础的底子不到位,复习! 所记知识会发布在CSDN与博客网站jirath.cn <Java基础复习>-常识与入门 一.Java语言的知识体系图 分为三部分 编程语言核心 ...
- Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用
Java数据结构之---Queue队列 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在 ...
- Java基础复习笔记系列 九 网络编程
Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...
- Java基础复习笔记系列 八 多线程编程
Java基础复习笔记系列之 多线程编程 参考地址: http://blog.csdn.net/xuweilinjijis/article/details/8878649 今天的故事,让我们从上面这个图 ...
- Java基础复习笔记系列 七 IO操作
Java基础复习笔记系列之 IO操作 我们说的出入,都是站在程序的角度来说的.FileInputStream是读入数据.?????? 1.流是什么东西? 这章的理解的关键是:形象思维.一个管道插入了一 ...
随机推荐
- 托管C++中System::String^ 转换为 char*
https://docs.microsoft.com/en-us/cpp/dotnet/how-to-convert-system-string-to-standard-string?view=vs- ...
- one vs all -- 将01分类器用于多类分类问题
大多数分类器都是01分类器,如logistic regression.当我们要将数据分为多类的时候, 可以用一种叫one-vs-all的方法将01分类器用于多类分类(mult-class classi ...
- xcode dyld: Library not loaded: @rpath/libswiftCore.dylib问题解决
app安装好了之后就报这个错误,这个时候可以将xcode工程clear一下,删除已经安装好的app,再重新安装即可
- 开源录屏软件Open Broadcaster Software
Open Broadcaster Software是一款开源录屏软件,功能强大,设计合理,其官方网址是https://obsproject.com/
- JavaScript基础修炼(14)
目录 一. PCM格式是什么 二. 浏览器中的音频采集处理 三. 需求实现 方案1——服务端FFmpeg实现编码 方案2——ScriptProcessorNode手动处理数据流 参考文献 示例代码托管 ...
- python 连接 hive数据库环境搭建
首先需要安装以下Python 包:(我用的是Python 2) 在安装Python包之前需要安装一些依赖工具: Debian/Ubuntu: apt-get install python-dev li ...
- CTF—攻防练习之ssh私钥泄露
攻防练习1 ssh私钥泄露 靶场镜像:链接: https://pan.baidu.com/s/1xfKILyIzELi_ZgUw4aXT7w 提取码: 59g0 首先安装打开靶场机 没办法登录,也没法 ...
- SpringBoot 和 SpringCloud 之间关系?
SpringBoot:专注于快速方便的开发单个个体微服务(关注微观):SpringCloud:关注全局的微服务协调治理框架,将SpringBoot开发的一个个单体微服务组合并管理起来(关注宏观):Sp ...
- 《Python编程从0到1》笔记1——表达式的风格(前缀、中缀、后缀)
运算符和运算数组成表达式.运算符和运算数的出现次序会影响表达式乃至程序设计语言的风格. 1.前缀表达式 前缀,是指运算符的位置在前.前缀风格的一个例子是函数调用,如求最大值函数:max(3, 2, 5 ...
- windows编程 使用C++实现多线程类
有时候我们想在一个类中实现多线程,主线程在某些时刻获得数据,可以“通知”子线程去处理,然后把结果返回.下面的实例是主线程每隔2s产生10个随机数,将这10随机数传给多线程类,让它接收到数据后马上打印出 ...