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

解法思路

使用递归算法进行处理。

汉诺塔的算法大概有3个步骤:

(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的更多相关文章

  1. java数据结构复习01

    1.数组 package javaDataStruct.array01; public class MyArray { private int[] arr; // 表示有效数据的长度 private ...

  2. Java数据结构和算法(二)顺序存储的树结构

    Java数据结构和算法(二)顺序存储的树结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 二叉树也可以用数组存储,可以和完 ...

  3. Java数据结构和算法(五)--希尔排序和快速排序

    在前面复习了三个简单排序Java数据结构和算法(三)--三大排序--冒泡.选择.插入排序,属于算法的基础,但是效率是偏低的,所以现在 学习高级排序 插入排序存在的问题: 插入排序在逻辑把数据分为两部分 ...

  4. Java数据结构和算法(三)--三大排序--冒泡、选择、插入排序

    三大排序在我们刚开始学习编程的时候就接触过,也是刚开始工作笔试会遇到的,后续也会学习希尔.快速排序,这里顺便复习一下 冒泡排序: 步骤: 1.从首位开始,比较首位和右边的索引 2.如果当前位置比右边的 ...

  5. 《Java基础复习》—常识与入门

    突然发现自己Java基础的底子不到位,复习! 所记知识会发布在CSDN与博客网站jirath.cn <Java基础复习>-常识与入门 一.Java语言的知识体系图 分为三部分 编程语言核心 ...

  6. Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用

    Java数据结构之---Queue队列 队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在 ...

  7. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

  8. Java基础复习笔记系列 八 多线程编程

    Java基础复习笔记系列之 多线程编程 参考地址: http://blog.csdn.net/xuweilinjijis/article/details/8878649 今天的故事,让我们从上面这个图 ...

  9. Java基础复习笔记系列 七 IO操作

    Java基础复习笔记系列之 IO操作 我们说的出入,都是站在程序的角度来说的.FileInputStream是读入数据.?????? 1.流是什么东西? 这章的理解的关键是:形象思维.一个管道插入了一 ...

随机推荐

  1. python读取在文件中以unicode编码方式转成中文

    row='\u4E09\u56FD\u6F14\u4E49' eval("u"+"\'"+row+"\'")

  2. 自定义ListView实现下拉刷新,下拉加载的功能

    package com.loaderman.myrefreshlistviewdemo; import android.content.Context; import android.util.Att ...

  3. 第九章 SpringCloud之Zuul路由

    ############Zuul简单使用################ 1.pom.xml <?xml version="1.0" encoding="UTF-8 ...

  4. PHP加速器eAccelerator安装

    程序说明 eAccelerator是一个自由开放源码php加速器,优化和动态内容缓存,提高了php脚本的缓存性能,使得PHP脚本在编译的状态下,对 服务器的开销几乎为零. 它还有对脚本起优化作用,以加 ...

  5. PP相关号码范围IMG设定

    一.定义订单号码范围——CO82 IMG> 生產> 現埸控制 > 主檔資料 > 訂單 > 定義訂單號碼範圍 可看到目前工單所訂義的區間(注意, 工單的號碼區間和CO的內部 ...

  6. crond服务总结

    昨天翻阅程序发现服务器端管理程序的启动方式很特别,在之前是由init进程启动程序脚本里的进程,昨天发现服务程序并没有在任何脚本中有启动的体现,但是服务程序确实是启动了,经过一番查找发现原来是crond ...

  7. vs2015中将复制过来的文件夹显示目录文件

    先将文件夹和文件复制到VS程序所在的位置,点击解决方案资源管理器上的“显示所有文件”按纽,展开这个文件夹,这样你就可以看到这个文件或者文件夹了,这时,这个文件或者文件夹是虚线构成的.你右击这个文件或者 ...

  8. spring boot-6.profile 多环境支持

    在正式项目中一般都会区分多个环境,一般至少分为开发环境,测试生产环境,生产环境,实际可能会有更加精细的区分,针对不同的环境,项目的配置可能需要切换,spring boot 提供了很方便的环境切换方式. ...

  9. [转帖]教你如何修改运行中的docker容器的端口映射

    教你如何修改运行中的docker容器的端口映射   在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当dock ...

  10. [转帖].NET Core 项目指定SDK版本

    .NET Core 项目指定SDK版本 https://www.cnblogs.com/stulzq/p/9503121.html 一. 版本里的坑 自从 .NET Core 2.1.0版本发布以后, ...