diff --git a/src/cn/edu/tju/rico/BinarySearchTree/BinarySearchTree.java b/src/cn/edu/tju/rico/BinarySearchTree/BinarySearchTree.java new file mode 100644 index 0000000..127448b --- /dev/null +++ b/src/cn/edu/tju/rico/BinarySearchTree/BinarySearchTree.java @@ -0,0 +1,159 @@ +package cn.edu.tju.rico.BinarySearchTree; + +public class BinarySearchTree { + + private TreeNode root; + + /** + * @description 根据已知序列构建二叉搜索树 + * @author rico + * @created 2017年6月3日 下午6:15:54 + * @param input + */ + public BinarySearchTree(int[] input) { + createBinarySearchTree(input); + } + + /** + * @description 根据已知序列构建二叉搜索树 + * @author rico + * @created 2017年6月3日 下午6:15:06 + * @param input + */ + public void createBinarySearchTree(int[] input) { + if (input != null) { + for (int i = 0; i < input.length; i++) { + root = insert(input[i], root); + } + } + } + + /** + * @description 二叉搜索树的搜索算法,递归算法 + * @author rico + * @created 2017年6月3日 下午3:27:43 + * @param target + * 目标值 + * @param root + * 二叉搜索树的根结点 + * @return + */ + public TreeNode search(int target, TreeNode root) { + TreeNode result = null; + if (root != null) { // 递归终止条件 + if (target == root.data) { // 递归终止条件 + result = root; + return result; + } else if (target < root.data) { // 目标值小于根结点值,从左子树查找 + result = search(target, root.left); + } else { // 目标值大于根结点值,从右子树查找 + result = search(target, root.right); + } + } + return result; + } + + /** + * @description 二叉搜索树的插入操作 + * @author rico + * @created 2017年6月3日 下午5:55:05 + * @param target + * @param node + * @return + */ + public TreeNode insert(int target, TreeNode node) { + if (search(target, node) == null) { + if (node == null) { + return new TreeNode(target); + } else { + if (target < node.data) { + node.left = insert(target, node.left); + } else { + node.right = insert(target, node.right); + } + } + } + return node; + } + + /** + * @description 删除搜索二叉树的制定结点 + * @author rico + * @created 2017年6月3日 下午8:43:29 + * @param target + * @param node + * @return + */ + public TreeNode remove(int target, TreeNode node) { + TreeNode tmp = null; + if (node != null) { + if (target < node.data) { // 从左子树删除 + node.left = remove(target, node.left); + } else if (target > node.data) { // 从右子树删除 + node.right = remove(target, node.right); + } else if (node.left != null && node.right != null) { // 找到待删除结点,且其左右子树不为空 + // 找到以待删除结点右子树的中序遍历第一个结点(最小结点) + tmp = node.right; + while (tmp.left != null) { + tmp = tmp.left; + } + + // 用最小结点补位待删除结点 + node.data = tmp.data; + + // 删除待删除结点右子树上补位结点 + node.right = remove(node.data, node.right); + } else { + if (node.left == null) { + node = node.right; + } else { + node = node.left; + } + } + } + return node; + } + + /** + * @description 中序遍历二叉搜索树,递归算法,升序排序 + * @author rico + * @created 2017年6月3日 下午3:52:54 + * @param root + */ + public void inOrder(TreeNode node) { + if (node != null) { + inOrder(node.left); + System.out.print(root.data + " "); + inOrder(node.right); + } + } + + /** + * @description 打印二叉搜索树 + * @author rico + * @created 2017年6月3日 下午6:08:42 + * @param node + */ + public void printTree(TreeNode node) { + if (node != null) { + System.out.print(node.data); + if (node.left != null || node.right != null) { + System.out.print("("); + printTree(node.left); + System.out.print(","); + printTree(node.right); + System.out.print(")"); + } + } + } + + /** + * @description 访问二叉搜索树的根结点 + * @author rico + * @created 2017年6月3日 下午3:54:49 + * @return + */ + public TreeNode getRoot() { + return root; + } +} diff --git a/src/cn/edu/tju/rico/BinarySearchTree/TreeNode.java b/src/cn/edu/tju/rico/BinarySearchTree/TreeNode.java new file mode 100644 index 0000000..e15ed64 --- /dev/null +++ b/src/cn/edu/tju/rico/BinarySearchTree/TreeNode.java @@ -0,0 +1,19 @@ + +package cn.edu.tju.rico.BinarySearchTree; + +public class TreeNode { + + public int data; + public TreeNode left; + public TreeNode right; + + public TreeNode(int data){ + this.data = data; + } + + @Override + public String toString() { + return "TreeNode [data=" + data + "]"; + } + +} diff --git a/src/cn/edu/tju/rico/backtrack/EightQueen.java b/src/cn/edu/tju/rico/backtrack/EightQueen.java new file mode 100644 index 0000000..ec8f295 --- /dev/null +++ b/src/cn/edu/tju/rico/backtrack/EightQueen.java @@ -0,0 +1,89 @@ +package cn.edu.tju.rico.backtrack; + +import java.util.Arrays; +import java.util.Date; + +/** + * Title: 八皇后问题(递归算法) Description: 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击, + * 即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 + * + * @author rico + * @created 2017年5月31日 下午4:54:17 + */ +public class EightQueen { + + private static final short N = 8; // 使用常量来定义,方便之后解N皇后问题 + private static int count = 0; // 结果计数器 + + public static void main(String[] args) { + Date begin = new Date(); + // 初始化棋盘,全部置0 + short chess[][] = new short[N][N]; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + chess[i][j] = 0; + } + } + + putQueenAtRow(chess, 0); + Date end = new Date(); + System.out.println("解决 " + N + " 皇后问题,用时:" + + String.valueOf(end.getTime() - begin.getTime()) + "毫秒,计算结果:" + + count); + } + + private static void putQueenAtRow(short[][] chess, int row) { + // 递归终止判断:如果row==N,则说明已经成功摆放了8个皇后 输出结果,终止递归 + if (row == N) { + count++; + System.out.println("第 " + count + " 种解:"); + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + System.out.print(chess[i][j] + " "); + } + System.out.println(); + } + return; + } + + short[][] chessTemp = chess.clone(); + + /** + * 向这一行的每一个位置尝试排放皇后 然后检测状态,如果安全则继续执行递归函数摆放下一行皇后 + */ + for (int i = 0; i < N; i++) { + // 摆放这一行的皇后,之前要清掉所有这一行摆放的记录,防止污染棋盘 + for (int j = 0; j < N; j++) + chessTemp[row][j] = 0; + + chessTemp[row][i] = 1; + + if (isSafety(chessTemp, row, i)) { + putQueenAtRow(chessTemp, row + 1); +// System.out.println("-----------"); +// for (int k = 0; k < N; k++) { +// for (int j = 0; j < N; j++) { +// System.out.print(chess[k][j] + " "); +// } +// System.out.println(); +// } + } + } + } + + private static boolean isSafety(short[][] chess, int row, int col) { + // 判断中上、左上、右上是否安全 + int step = 1; + while (row - step >= 0) { + if (chess[row - step][col] == 1) // 中上 + return false; + if (col - step >= 0 && chess[row - step][col - step] == 1) // 左上 + return false; + if (col + step < N && chess[row - step][col + step] == 1) // 右上 + return false; + + step++; + } + return true; + } +} \ No newline at end of file diff --git a/src/cn/edu/tju/rico/sort/QuickSort_PartitionOnly.java b/src/cn/edu/tju/rico/sort/QuickSort_PartitionOnly.java new file mode 100644 index 0000000..e80d983 --- /dev/null +++ b/src/cn/edu/tju/rico/sort/QuickSort_PartitionOnly.java @@ -0,0 +1,49 @@ +package cn.edu.tju.rico.sort; + +import java.util.Arrays; + + +/** + * Title:快速排序的变形 + * Description: 本质上不断调用经典快排的划分算法 + * 时间复杂度:O(n^2) + * @author rico + * @created 2017年6月2日 下午9:10:43 + */ +public class QuickSort_PartitionOnly { + /** + * @description 依次以数组中的每个元素为基准点进行划分, + * 直到遍历所有元素都 + * @author rico + * @param array + */ + public void quicksort(int[] array) { + if (array != null && array.length != 0) { + for (int i = 0; i < array.length; i++) { + // 以下是快排的划分算法 + int base_index = 0; + int base = array[i]; + base_index = i; + for (int j = i+1; j < array.length; j++) { + if (array[j] <= base ) { + base_index ++; + if (base_index != j) { + int temp = array[base_index]; + array[base_index] = array[j]; + array[j] = temp; + } + } + } + array[i] = array[base_index]; + array[base_index] = base; + System.out.println(Arrays.toString(array)); + } + } + } + + public static void main(String[] args) { +// int[] array = { 1, 2, 3, 2, 2, 2, 5, 4, 2 }; + int[] array = { 1, 2, 3, 5, 0, 4, 9, 2, 6 }; + new QuickSort_PartitionOnly().quicksort(array); + } +} diff --git a/src/cn/edu/tju/rico/test/BinarySearchTreeTest.java b/src/cn/edu/tju/rico/test/BinarySearchTreeTest.java new file mode 100644 index 0000000..a2e8067 --- /dev/null +++ b/src/cn/edu/tju/rico/test/BinarySearchTreeTest.java @@ -0,0 +1,35 @@ +package cn.edu.tju.rico.test; + +import cn.edu.tju.rico.BinarySearchTree.BinarySearchTree; + +public class BinarySearchTreeTest { + public static void main(String[] args) { + int[] input = {53,78,65,17,87,9,81,45,23}; + BinarySearchTree tree = new BinarySearchTree(input); + + System.out.println("中序遍历二叉搜索树:"); + tree.inOrder(tree.getRoot()); + System.out.println(); + System.out.println("\n------------------------\n"); + System.out.println("打印二叉搜索树:"); + tree.printTree(tree.getRoot()); + System.out.println(); + System.out.println("\n------------------------\n"); + + System.out.println("二叉搜索树搜索目标值:"); + System.out.println(tree.search(23, tree.getRoot())); + System.out.println("\n------------------------\n"); + + System.out.println("向二叉搜索树插入目标值:"); + tree.insert(10, tree.getRoot()); + tree.printTree(tree.getRoot()); + System.out.println(); + System.out.println("\n------------------------\n"); + + System.out.println("向二叉搜索树删除目标值:"); + tree.remove(78, tree.getRoot()); + tree.printTree(tree.getRoot()); + System.out.println(); + System.out.println("\n------------------------\n"); + } +} diff --git a/src/cn/edu/tju/rico/test/SortTest.java b/src/cn/edu/tju/rico/test/SortTest.java index 0529a5d..025e501 100644 --- a/src/cn/edu/tju/rico/test/SortTest.java +++ b/src/cn/edu/tju/rico/test/SortTest.java @@ -57,7 +57,7 @@ public static void main(String[] args) { System.out.println("\n----------------------\n"); System.out.println("希尔排序 : "); - int[] target7 = { 21, 25, 49, 25, 16, 8, 31, 41 }; + int[] target7 = { 21, 25, 49, 25, 16, 8, 31, 41,1,16 }; System.out.println("原数组 : " + Arrays.toString(target7)); ShellSort.shellSort(target7); System.out.println(Arrays.toString(target7)); diff --git a/src/cn/edu/tju/rico/tree/BinaryTree.java b/src/cn/edu/tju/rico/tree/BinaryTree.java index b07f916..6642877 100644 --- a/src/cn/edu/tju/rico/tree/BinaryTree.java +++ b/src/cn/edu/tju/rico/tree/BinaryTree.java @@ -132,6 +132,60 @@ public void createBinaryTree(String exp) { node = null; // node链入后,置空 } } + + /** + * @description 根据广义表表达式创建树 + * @author rico + * @created 2017年5月22日 下午3:16:01 + * @param exp 广义表 + */ + public static Node createBinaryTree(String exp, Node root) { + LinkedList stack = new LinkedList(); // 辅助栈 + Node node = null; // 新结点 + Node temp = null; // 用于入栈 + Node parent = null; // 父亲结点 + boolean flag = false; // true 表示链入到父结点的左孩子位置,false表示链入父结点的右孩子位置 + + for (int i = 0; i < exp.length(); i++) { // 逐个读入表达式的各个字符 + char c = exp.charAt(i); + switch (c) { + case '(': // 当前节点有孩子节点,入栈以便设置其孩子 + stack.push(temp); + flag = true; + break; + case ')': // 设置好了栈顶节点的孩子,出栈 + stack.pop(); + break; + case ',': // 当前节点无孩子,不需要设置其孩子节点,因此不需要入栈 + flag = false; + break; + default: // 创建根据内容创建节点 + node = new Node(c); + break; + } + + // 若树不存在,则创建树的根结点 + if (root == null) { + root = node; + } + + // 为栈顶节点链入子女 + if (!stack.isEmpty()) { + if (node != null) { // 当读入的是'('、')'、','字符时,略过 + parent = stack.peek(); + if (flag) { + parent.left = node; + } else { + parent.right = node; + } + } + } + + temp = node; // 用于入栈 + node = null; // node链入后,置空 + } + return root; + } /** * @description 广序/层次遍历,工作队列