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.流是什么东西? 这章的理解的关键是:形象思维.一个管道插入了一 ...
随机推荐
- SpringMvc中@PathVariable注解简单的用法
@PathVariable /** * @PathVariable 可以来映射 URL 中的占位符到目标方法的参数中. * @param id * @return */ jsp页面请求 <a h ...
- Java内存泄漏分析和预防
1. 什么是内存泄漏?有什么危害 书面说法: 内存泄漏:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着. 在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个 ...
- 1.4 Navicat Mybatis 占坑
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...
- 代码实现:编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n
import java.util.Scanner; //编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n public ...
- Python之取整
在编程过程中数据处理是不可避免的,很多时候都需要根据需求把获取到的数据进行处理,取整则是最基本的数据处理.取整的方式则包括向下取整.四舍五入.向上取整等等.下面就来看看在Python中取整的几种方法吧 ...
- python的一些方法
1.如何循环获得下标,使用 enumerate ints = ['a','b','c','d','e','f'] for idx, val in enumerate(ints): print idx, ...
- Message的定义類型
SAP通过Message来回执程序的执行状态.使用Tcode:SE91. SAP將Message分为不同的类,如下图显示为ZF环境下ZMM01类相关Message列表. Message short t ...
- freetype HarfBuzz fontconfig Cairo 编译顺序
There is also a circular dependency between freetype and HarfBuzz. Note that fontconfig and Cario ar ...
- java 接口default的判断规则
1.前言 jdk1.8中新增加了default关键字,就是在接口中可以增加默认实现. 因为改动接口所有的实现类都要改动,所以增加了default关键字后不需要修改其他类,默认给所有实现类增加了方法. ...
- 论文翻译:HetConv-Heterogeneous Kernel-Based Convolutions for Deep CNNs
Abstract 我们提出了一种新颖的深度学习架构,其中卷积操作利用了异构内核.与标准卷积运算相比,所提出的HetConv(基于异构内核的卷积)减少了计算(FLOPs)和参数的数量,同时仍保持表示效率 ...