顺序存储二叉树
二叉树的节点以数组的方式存放
- 顺序二叉树通常只考了完全二叉树
- 第 n 个元素的左子节点为 2*n+1
- 第 n 个元素的右子节点为 2*n+2
- 第 n 个元素的父节点为 (n-1)/ 2 (向下取整)
- n:表示二叉树中的第几个元素(按0开始编号)
package search;
import java.util.ArrayList;
public class ArrayBinaryTree {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7};
ArrayBinary arrayBinary = new ArrayBinary(arr);
//arrayBinary.preOrder();
//arrayBinary.infixOrder(0);
arrayBinary.postOrder(0);
}
}
// store binary tree using array
class ArrayBinary{
private int[] arr;
public ArrayBinary(int[] arr) {
this.arr = arr;
}
// override preOrder
public void preOrder(){
this.preOrder(0);
}
// method
public void preOrder(int index){
// if arr is empty
if(arr == null || arr.length==0){
System.out.println("empty array");
}
// print current ele
System.out.println(arr[index]);
// traverse left recursively
if((index*2+1)<arr.length){
preOrder(2*index+1);
}
// traverse right recursively
if(index*2+2<arr.length){
preOrder(index*2+2);
}
}
public void infixOrder(int index){
if(arr==null||arr.length==0){
System.out.println("empty arr");
}
if((index*2+1)<arr.length){
infixOrder(2*index+1);
}
System.out.println(arr[index]);
if((index*2+2)<arr.length){
infixOrder(2*index+2);
}
}
public void postOrder(int index){
if(arr==null || arr.length==0){
System.out.println("empty");
}
if((index*2+1)<arr.length){
postOrder(index*2+1);
}
if((index*2+2)<arr.length){
postOrder(index*2+2);
}
System.out.println(arr[index]);
}
}
线索化二叉树
-
n 个节点的二叉链表中含有 n+1 个空指针,利用二叉链表中的空指针域,存放指向该节点再某种遍历次序下的前驱和后继节点的指针(这种附加的指针称为“线索”)
-
线索二叉树:threaded binary tree
-
一个节点的前一个节点,称为前驱节点
-
一个节点的后一个节点,称为后继节点
中序遍历结果 {8,3,10,1,14,6}
3的前驱节点为8,后继节点为10
10的前驱节点为3,后继节点为1
// 中序
class ThreadBinaryTree{
private HeroNode root;
// need a pointer points to current node's predecessor node
private HeroNode pre = null;
public void setRoot(HeroNode root) {
this.root = root;
}
// threaded it! infix order
// threaded node(param)
public void threadedNodes(HeroNode node){
// if node == null, cannot be threaded
if(node==null){
return;
}
// threaded left tree first
threadedNodes(node.getLeft());
// thread current node
// predecessor node
if(node.getLeft()==null){
node.setLeft(pre); // left pointer of current node points to pre
node.setLeftType(1); // the type of current node's left pointer points to predecessor node
}
// successor node
if(pre!=null && pre.getRight()==null){
// right pointer of predecessor points to current node
pre.setRight(node);
// edit right pointer's type of predecessor node
pre.setRightType(1);
}
// !!! 每处理一个节点后,让当前节点是下一个节点的前驱节点
pre = node;
// threaded right tree first
threadedNodes(node.getRight());
}
}
class HeroNode{
private int id;
private String name;
private HeroNode left; // default null
private HeroNode right;
// note:
// 1. if leftType == 0, means it points to left tree
// if leftType == 1, points to predecessor node
// 2. if rightType == 0, points to right tree
// if rightType == 1, points to successor node
private int leftType;
private int rightType;
public int getLeftType() {
return leftType;
}
public void setLeftType(int leftType) {
this.leftType = leftType;
}
public int getRightType() {
return rightType;
}
public void setRightType(int rightType) {
this.rightType = rightType;
}
}
完整代码:package tree.ThreadedBinaryTree; class ThreadedBinaryTreeDemo
遍历线索化二叉树
public void threadedList(){
// define a variable store current node, from root
HeroNode node = root;
while(node!=null){
// 循环的找到 leftType==1的节点,第一个找到的就是8节点
// 后面随着遍历而变化,因为当 leftType==1 时,说明该节点是按照线索化处理后
// 的有效节点
while(node.getLeftType()==0){
node = node.getLeft();
}
// print current node
System.out.println(node);
// 如果当前节点的右指针指向的是后继节点,就一直输出
while(node.getRightType()==1){
// get predecessor of current node
node = node.getRight();
System.out.println(node);
}
// replace node whose type is not 1
node = node.getRight();
}
}
二叉树的应用
-
堆排序,是一种选择排序,时间复杂度为 O(nlogn) 线性对数阶,不稳定的排序
堆:完全二叉树,
- 每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆;特点:arr[i] >= arr[2/timesi+1] && arr[i] >= arr[2*i+2];升序
- 每个节点的值都小于或等于其左右孩子的节点的值,称为小顶堆;arr[i] <= arr[2/timesi+1] && arr[i] <= arr[2*i+2];降序
堆排序基本思想
- 将待排序序列构造成一个大顶堆
- 此时,整个序列的最大值就是堆顶的根节点
- 将其与末尾元素进行交换,此时末尾就为最大值
- 然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。如此反复执行,便能得到一个有序序列
package tree;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
// ascending
int arr[] = {4,6,8,5,9};
heapSort(arr);
}
// heap sort
public static void heapSort(int arr[]){
// adjustHeap(arr,1,arr.length);
// System.out.println("first:"+ Arrays.toString(arr));
// adjustHeap(arr,0,arr.length);
// System.out.println("second:"+ Arrays.toString(arr));
int temp = 0;
for(int i = arr.length/2-1;i>=0;i--){
adjustHeap(arr,i,arr.length);
}
// get a big top heap
// sort; swap top node with the last node of the tree
// adjust tree to big top heap
for(int j = arr.length-1;j>0;j--){
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr,0,j);
}
System.out.println("second:"+ Arrays.toString(arr));
}
// array(binary tree) --> big top heap
/**
* funtion: adjust the tree with non-leaf node i to a big top heap
* eg: arr = {4,6,8,5,9} => i = 1 => adjustHeap(arr,1,) => {4,9,8,5,6}
* eg: next time: i = 0 => adjustHeap(arr,0,) => {9,6,8,5,4}
* @param arr array waiting for adjustment
* @param i index of non-leaf node
* @param length number of nodes waiting for adjustment
*/
public static void adjustHeap(int arr[],int i,int length){
int temp = arr[i]; // save current value
for(int k = i*2+1;k<length;k = k*2+1){
// 2*i+1: left node of non-leaf node whose index is i
if(k+1<length && arr[k]<arr[k+1]){ // value of left node is smaller than right node
k++; // k point to right node
}
if(arr[k]>temp){ // child node is bigger than parent node(temp)
arr[i] = arr[k]; // assign bigger value to non-leaf node
i = k; // k may still have sub-tree need to be adjusted
}else{
break;
}
}
// when out of for loop, the biggest number of tree whose father is i
// is put on the top
arr[i] = temp; // put temp to the position after adjustment
}
}