数据结构与算法 15 顺序存储二叉树 线索化二叉树 堆排序

顺序存储二叉树

二叉树的节点以数组的方式存放

  • 顺序二叉树通常只考了完全二叉树
  • 第 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();
        }
    }

二叉树的应用

  1. 堆排序,是一种选择排序,时间复杂度为 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];降序

堆排序基本思想

  1. 将待排序序列构造成一个大顶堆
  2. 此时,整个序列的最大值就是堆顶的根节点
  3. 将其与末尾元素进行交换,此时末尾就为最大值
  4. 然后将剩余 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

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值