• 二叉查找树转换为顺序的双向链表


    如题将二叉查找树转换为排序的双向链表,要求输入一棵二叉查找树,输出为一个排好序的双向链表,要求不能创建新的节点,只能改变指针的指向。

    这个问题的考察点涉及到二叉查找树的概念,以及如何建立二叉查找树,双向链表的概念,以及二叉查找树和排序的双向链表的转换。

    二叉查找树又称为有序二叉树,是指一颗空树或者具有以下性质的二叉树:

    • 若任意节点的左子树不为空,则左子树上所有节点的值均小于等于根节点的值;
    • 若任意节点的右子树不为空,则右子树上所有节点的值均大于等于根节点的值;
    • 任意节点的左右子树也分别为二叉查找树;
    • 没有键值相等的节点;

    二叉查找树对任何节点x,其左子树中的关键字最大不超过key[x],其右子树中的关键字最小不小于key[x],不同的二叉查找树可以表示同一组值,在有关查找树的操作中,大部分操作的最坏情况运行时间与树的高度成正比。

    对于本题要将二叉查找树转换为排序的双向链表,可以从递归的思想来考虑,为了将整棵树转换为顺序双向链表则可以将问题分解为,把左子树转换为顺序的双向链表,把右子树转换为顺序的双向链表,同时需要注意交换节点指针。

    head为二叉查找树的key最小的节点min(root)

    tail为二叉查找树的key最大的节点max(root)

    root为二叉查找树的根节点

    treeToLinkedList(head, tail, root) {

    treeToLinkedList(head, max(root.left), root.left)

    treeToLinkedList(min(root.right), tail, root.right)

    }

    具体实现如下:

    public class TreeToList<Key extends Comparable<Key>> {
        private Node root;
        private class Node {
            Key key;
            Node left;
            Node right;
            Node(Key key) {
                this.key = key;
            }
        }
    
        /* 向二叉查找树中插入元素,用于构建二叉查找树 */
        public void put(Key key) {
            root = put(root, key);
            //System.out.println(root.key + " " + root.left + " " + root.right);
        }
    
        private Node put(Node x, Key key) {
            /* 如果要插入的根节点为空则直接创建一个新节点作为根节点 */
            if (x == null) {
                return new Node(key);
            }
    
            int cmp = key.compareTo(x.key);
            /* 如果要插入的节点key小于根节点的key则需要将key插入到
            *  根节点的左子树,如果大于根节点的key则需要将key插入到
            *  根节点的右子树,否则直接返回 */
            if (cmp < 0) {
                x.left = put(x.left, key);
            } else if (cmp > 0) {
                x.right = put(x.right, key);
            } else {
                return null;
            }
    
            return x;
        }
    
        public Key min() {
            return min(root).key;
        }
    
        /* 获取二叉查找树中key最小的节点 */
        private Node min(Node x) {
            /* 如果x的左子树为空则x作为根节点即为二叉查找树中key最小的节点,
            *  如果x的左子树不为空则需要递归在x的左子树中查找key最小的节点*/
            if (x == null) {
                return null;
            }
    
            if (x.left == null) {
                return x;
            }
            return min(x.left);
        }
    
        public Key max() {
            return max(root).key;
        }
    
        /* 获取二叉查找树中key最大的节点 */
        private Node max(Node x) {
            if (x == null) {
                return null;
            }
    
            if (x.right == null) {
                return x;
            }
            return max(x.right);
        }
    
        public void treeToList() {
            treeToList(min(root), max(root), root);
    
            Node tmp = min(root);
            while (tmp != null) {
                System.out.print(tmp.key + "->");
                tmp = tmp.right;
            }
            System.out.println();
            tmp = max(root);
            while (tmp != null) {
                System.out.print(tmp.key + "->");
                tmp =tmp.left;
            }
        }
    
        /* 将二叉查找树转换为顺序的双向链表,head为以x为根节点的二叉查找树中key
        *  最小的节点,tail为以x为根节点的二叉查找树中key最大的节点 */
        private void treeToList(Node head, Node tail, Node x) {
            if (x == null) {
                head = null;
                tail = null;
                return;
            }
    
            Node lmax = max(x.left);
            Node rmin = min(x.right);
            treeToList(head, lmax, x.left);
            treeToList(rmin, tail, x.right);
            if (lmax != null) {
                lmax.right = x;
                x.left = lmax;
            }
    
            if (rmin != null) {
                rmin.left = x;
                x.right = rmin;
            }
        }
    
        public static void main(String[] args) {
            TreeToList<Integer> ttl = new TreeToList<Integer>();
            int[] array = {10, 6, 14, 4, 8, 12, 16};
            for (int i = 0; i < array.length; i++) {
                ttl.put(array[i]);
            }
            System.out.println("min: " + ttl.min() + " max: " + ttl.max());
            ttl.treeToList();
        }
    }
     
    ------------------------------- 问道,修仙 -------------------------------
  • 相关阅读:
    制作基于OK6410的文件系统(2.修改busybox文件系统,使之能启动)
    [转]SlickEdit 2012
    移植TPLINK TLWN721N 驱动到micro2440(by liukun321咕唧咕唧)
    擦,买到了伪劣的SD卡
    Slickedit中文显示与输入
    OMAP3530mini调试笔记(2)
    最近在做linux的移植工作
    嵌入式linux启动时运行的inittab文件(zz)
    OMAP3530mini调试笔记(1)
    Ubuntu中音量调节无效的解决方法
  • 原文地址:https://www.cnblogs.com/elvalad/p/4133428.html
Copyright © 2020-2023  润新知