实现一个二叉查找树,并且支持插入、删除、查找操作
//插入元素
BinarySearchTreeNode insert(BinarySearchTreeNode root, int data) {
if (root == null)
root = new BinarySearchTreeNode(data);//若原树为空, 生成并返回一个结点的二叉搜索树
else {
if (data < root.getData()) //开始找要插入元素的位置
root.setLeft(insert(root.getLeft(),data));//递归插入左子树
else if (data > root.getData())
root.setRight(insert(root.getRight(),data));//递归插入右子树
}
return root;
}
//删除元素
BinarySearchTreeNode delete(BinarySearchTreeNode root, int data) {
BinarySearchTreeNode temp;
if (root == null)
System.out.println("要删除的元素未找到");
else if (data < root.getData())
root.setLeft(delete(root.getLeft(),data));//左子树递归删除
else if (data > root.getData())
root.setRight(delete(root.getRight(),data));//右子树递归删除
else { //找到要删除的结点
if (root.getLeft() != null && root.getRight() != null) { //被删除结点有左右两个子结点
temp = findMin(root.getRight());//在右子树中找最小的元素填充删除结点
root.setData(temp.getData());
root.setRight(delete(root.getRight(),root.getData()));//在删除结点的右子树中删除最小元素
}else { //被删除结点有一个或无子结点
temp = root;
if (root.getLeft() == null) //有右孩子或无子结点
root = root.getRight();
else if (root.getRight() == null) //有左孩子或无子结点
root = root.getLeft();
temp = null;
}
}
return root;
}
//查找元素:递归方法
BinarySearchTreeNode find(BinarySearchTreeNode root, int data) {
if (root == null)
return null;//查询失败
if (data < root.getData())
return find(root.getLeft(),data);//在左子树中继续查找
else if (data > root.getData())
return find(root.getRight(),data);//在右子树中继续查找
else
return root;//查找成功, 返回找到的结点的地址
}
//查找元素:非递归方法
BinarySearchTreeNode iterFind(BinarySearchTreeNode root, int data) {
while (root != null) {
if (data < root.getData())
root = root.getLeft();//向左子树中移动, 继续查找
else if (data > root.getData())
root = root.getRight();//向右子树中移动, 继续查找
else
return root;//查找成功, 返回找到的结点的地址
}
return null;//查询失败
}
实现查找二叉查找树中某个节点的后继、前驱节点
/**
* 寻找一个节点的后继节点和前驱节点
*/
public class SuccessorNode {
private static class Node {
private Integer value;
private Node left;
private Node right;
private Node parent;
public Node(int data) {
this.value = data;
}
}
/**
* 传入一个node,返回该node的后继节点
*
* @param node
* @return
*/
public static Node getSuccessorNode(Node node) {
if (node == null) {
return null;
}
if (node.right != null) {
return getMostLeft(node.right);
} else {
Node parent = node.parent;
while (parent != null && node != parent.left) {
node = parent;
parent = node.parent;
}
return parent;
}
}
/**
* 返回node为根节点的最左边节点
*
* @param node
* @return
*/
private static Node getMostLeft(Node node) {
while (node.left != null) {
node = node.left;
}
return node;
}
/**
* 返回node节点的前驱节点
*
* @param node
* @return
*/
public static Node getPioneerNode(Node node) {
if (node == null) {
return node;
}
if (node.left != null) {
return getMostRight(node.left);
} else {
Node parent = node.parent;
while (parent != null && node != parent.right) {
node = parent;
parent = node.parent;
}
return parent;
}
}
/**
* 返回以node为根节点的最右边节点
*
* @param node
* @return
*/
private static Node getMostRight(Node node) {
while (node.right != null) {
node = node.right;
}
return node;
}
public static void main(String[] args) {
Node head = new Node(6);
head.parent = null;
head.left = new Node(3);
head.left.parent = head;
head.left.left = new Node(1);
head.left.left.parent = head.left;
head.left.left.right = new Node(2);
head.left.left.right.parent = head.left.left;
head.left.right = new Node(4);
head.left.right.parent = head.left;
head.left.right.right = new Node(5);
head.left.right.right.parent = head.left.right;
head.right = new Node(9);
head.right.parent = head;
head.right.left = new Node(8);
head.right.left.parent = head.right;
head.right.left.left = new Node(7);
head.right.left.left.parent = head.right.left;
head.right.right = new Node(10);
head.right.right.parent = head.right;
Node test = head.left.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left.left.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left.right.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right.left.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right.right; // 10's next is null
System.out.println(test.value + " next: " + getSuccessorNode(test));
}
}
实现二叉树前、中、后序以及按层遍历
import com.ccut.aaron.stack.LinkedStack;
public class BinaryTree {
//前序遍历递归的方式
public void preOrder(BinaryTreeNode root){
if(null!=root){
System.out.print(root.getData()+"\t");
preOrder(root.getLeft());
preOrder(root.getRight());
}
}
//前序遍历非递归的方式
public void preOrderNonRecursive(BinaryTreeNode root){
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
while(true){
while(root!=null){
System.out.print(root.getData()+"\t");
stack.push(root);
root=root.getLeft();
}
if(stack.isEmpty()) break;
root=stack.pop();
root=root.getRight();
}
}
//中序遍历采用递归的方式
public void inOrder(BinaryTreeNode root){
if(null!=root){
inOrder(root.getLeft());
System.out.print(root.getData()+"\t");
inOrder(root.getRight());
}
}
//中序遍历采用非递归的方式
public void inOrderNonRecursive(BinaryTreeNode root){
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
while(true){
while(root!=null){
stack.push(root);
root=root.getLeft();
}
if(stack.isEmpty())break;
root=stack.pop();
System.out.print(root.getData()+"\t");
root=root.getRight();
}
}
//后序遍历采用递归的方式
public void postOrder(BinaryTreeNode root){
if(root!=null){
postOrder(root.getLeft());
postOrder(root.getRight());
System.out.print(root.getData()+"\t");
}
}
//后序遍历采用非递归的方式
public void postOrderNonRecursive(BinaryTreeNode root){
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
while(true){
if(root!=null){
stack.push(root);
root=root.getLeft();
}else{
if(stack.isEmpty()) return;
if(null==stack.lastElement().getRight()){
root=stack.pop();
System.out.print(root.getData()+"\t");
while(root==stack.lastElement().getRight()){
System.out.print(stack.lastElement().getData()+"\t");
root=stack.pop();
if(stack.isEmpty()){
break;
}
}
}
if(!stack.isEmpty())
root=stack.lastElement().getRight();
else
root=null;
}
}
}
//层序遍历
public void levelOrder(BinaryTreeNode root){
BinaryTreeNode temp;
Queue<BinaryTreeNode> queue=new LinkedList<BinaryTreeNode>();
queue.offer(root);
while(!queue.isEmpty()){
temp=queue.poll();
System.out.print(temp.getData()+"\t");
if(null!=temp.getLeft())
queue.offer(temp.getLeft());
if(null!=temp.getRight()){
queue.offer(temp.getRight());
}
}
}
public static void main(String[] args) {
BinaryTreeNode node10=new BinaryTreeNode(10,null,null);
BinaryTreeNode node8=new BinaryTreeNode(8,null,null);
BinaryTreeNode node9=new BinaryTreeNode(9,null,node10);
BinaryTreeNode node4=new BinaryTreeNode(4,null,null);
BinaryTreeNode node5=new BinaryTreeNode(5,node8,node9);
BinaryTreeNode node6=new BinaryTreeNode(6,null,null);
BinaryTreeNode node7=new BinaryTreeNode(7,null,null);
BinaryTreeNode node2=new BinaryTreeNode(2,node4,node5);
BinaryTreeNode node3=new BinaryTreeNode(3,node6,node7);
BinaryTreeNode node1=new BinaryTreeNode(1,node2,node3);
BinaryTree tree=new BinaryTree();
//采用递归的方式进行遍历
System.out.println("-----前序遍历------");
tree.preOrder(node1);
System.out.println();
//采用非递归的方式遍历
tree.preOrderNonRecursive(node1);
System.out.println();
//采用递归的方式进行遍历
System.out.println("-----中序遍历------");
tree.inOrder(node1);
System.out.println();
//采用非递归的方式遍历
tree.inOrderNonRecursive(node1);
System.out.println();
//采用递归的方式进行遍历
System.out.println("-----后序遍历------");
tree.postOrder(node1);
System.out.println();
//采用非递归的方式遍历
tree.postOrderNonRecursive(node1);
System.out.println();
//采用递归的方式进行遍历
System.out.println("-----层序遍历------");
tree.levelOrder(node1);
System.out.println();
}
}
实现一个小顶堆、大顶堆、优先级队列
/**
* 小顶堆/最小堆实现
*
*
*
*/
public class MinHeap {
// 堆得存储结构:数组
private int[] data;
/**
* 构造方法:传入一个数组,并转换为一个最小堆
*
* @param data
*/
public MinHeap(int[] data) {
this.data = data;
buildHeap();
}
/**
* 将数组转化为最小堆
*/
private void buildHeap() {
//完全二叉树只有数组下标小于或等于 (data.length) / 2 - 1 的元素有孩子结点,遍历这些结点。
//比如上面的图中,数组有10个元素, (data.length) / 2 - 1的值为4,a[4]有孩子结点,但a[5]没有
//即,从下自上开始堆化(从最下层非叶子节点开始)
for (int i = (data.length) / 2 - 1; i >= 0; i--) {
heapify(i);
}
}
/**
* 从当前节点开始堆化
*
* @param i
*/
private void heapify(int i) {
// 获取左右节点数组下标
int l = left(i);
int r = right(i);
// 假定的当前节点、左子节点、右子节点中 最小值的下标
int smallest = i;
// 存在左子节点,且左子节点的值小于当前节点的值
if (l < data.length && data[l] < data[i])
smallest = l;
// 存在右子节点,且右子节点的值小于当前节点的值
if (r < data.length && data[r] < data[i])
smallest = r;
// 左右结点的值都大于根节点,直接return
if (i == smallest)
return;
// 将最小值与当前节点互换位置
swap(i, smallest);
// 从之前最小值节点位置重新堆化
heapify(smallest);
}
/**
* 获取右节点的数组下标
*
* @param i
* @return
*/
private int right(int i) {
return (i + 1) << 1;
}
/**
* 获取左节点的数组下标
*
* @param i
* @return
*/
private int left(int i) {
return ((i + 1) << 1) - 1;
}
/**
* 交换元素位置
*
* @param i
* @param j
*/
private void swap(int i, int j) {
int tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
/**
* 获取堆中最小元素,即根元素
*
* @return
*/
public int getRoot() {
return data[0];
}
/**
* 替换根元素,并重新heapify
*
* @param root
*/
public void setRoot(int root) {
data[0] = root;
heapify(0);
}
}
实现堆排序
上次写过了。
利用优先级队列合并 K 个有序数组
1.
import java.util.Arrays;
class Solution {
public static int[] MergeArrays(int[][] array) {
int N = array.length, L;
if (N == 0)
return new int[0];
else {
L = array[0].length;
for (int i = 1; i < N; i++)
if (L != array[i].length)
return new int[0];
}
int[] result = new int[N * L];
for (int i = 0; i < N; i++)
for (int j = 0; j < L; j++)
result[i * L + j] = array[i][j];
Arrays.sort(result);
return result;
}
}
2.
import java.util.PriorityQueue;
import java.util.Arrays;
import java.util.Comparator;
public class SortedArraysMerge {
static class Node {
int value;
int idx;
public Node(int value, int idx) {
this.value = value;
this.idx = idx;
}
}
public static int[] MergeArrays(int[][] arr) {
int N = arr.length, L;
if (N == 0)//此时传入数组为空
return new int[0];
else {//判断数组是否符合规范
L = arr[0].length;
for (int i = 1; i < N; i++)
if (arr[i].length != L)
return new int[0]; //此时数组不规范
}
int[] result = new int[N * L];
int[] index = new int[N];
Arrays.fill(index, 0, N, 0);
PriorityQueue<Node> queue = new PriorityQueue<Node>(new Comparator<Node>() {
@Override
public int compare(Node n1, Node n2) {
if (n1.value < n2.value)
return -1;
else if (n1.value > n2.value)
return 1;
else
return 0;
}
});
for (int i = 0; i < N; i++) {
Node node = new Node(arr[i][index[i]++], i);
queue.offer(node);
}
System.out.println("" + queue.size());
int idx = 0;
while (idx < N * L) {
Node minNode = queue.poll();
result[idx++] = minNode.value;
if (index[minNode.idx] < L) {
queue.offer(new Node(arr[minNode.idx][index[minNode.idx]], minNode.idx));
index[minNode.idx]++;
}
}
return result;
}
}
求一组动态数据集合的最大 Top K