二叉树、链表算法

二叉树

// 创建节点
function Node(data, left, right) {
    this.data = data
    this.left = left
    this.right = right
    this.show = () => this.data
}

// 二叉查找树
function BST() {
    this.root = null

    this.insert = function (data) {
        let node = new Node(data, null, null);

        // 如果 BST.root === null ,那么就将节点作为根节点
        // 如果 BST.root !== null ,将插入节点进行一个比较,小于根节点,拿到左边的节点,否则拿右边,再次比较、递归。
        if (this.root === null) {
            this.root = node
        } else {
            let current = this.root;
            let parent;
            while (true) {
                parent = current;
                if (data < current.data) {
                    current = current.left; // 到左子树
                    if (current === null) {  // 如果左子树为空,说明可以将node插入在这里
                        parent.left = node;
                        break;  // 跳出while循环
                    }
                } else {
                    current = current.right;
                    if (current === null) {
                        parent.right = node;
                        break;
                    }
                }
            }
        }
    }

    // 中序
    this.inOrder = function () {
        const arr = []
        const _inOrder = (node) => {
            if (node !== null) {
                //如果不是null,就一直查找左变,因此递归
                _inOrder(node.left);
                //递归结束,打印当前值
                arr.push(node.show())
                //上一次递归已经把左边搞完了,右边
                _inOrder(node.right);
            }
        }
        _inOrder(this.root)
        return arr
    }

    // 前序
    this.preOrder = function () {
        const arr = []
        const _preOrder = (node) => {
            if (node !== null) {
                //根左右
                arr.push(node.show())
                _preOrder(node.left);
                _preOrder(node.right);
            }
        }
        _preOrder(this.root)
        return arr
    }

    // 后序
    this.postOrder = function () {
        const arr = []
        const _postOrder = (node) => {
            if (node !== null) {
                //左右根
                _postOrder(node.left);
                _postOrder(node.right);
                arr.push(node.show())
            }
        }
        _postOrder(this.root)
        return arr
    }

    // 最小值: 最左子树的叶子节点
    this.getMin = function () {
        let current = this.root;
        while (current.left !== null) {
            current = current.left;
        }
        return current.data;
    }

    // 最大值: 最右子树的叶子节点
    this.getMax = function () {
        let current = this.root;
        while (current.right !== null) {
            current = current.right;
        }
        return current.data;
    }

    // 特定值: target与current进行比较,如果比current大,在current.right进行查找,反之类似
    this.find = function (target) {
        let current = this.root
        let [layer, cols] = [0, []]
        while (current !== null) {
            layer++
            if (target === current.data) {
                const col = parseInt(cols.join(''), 2)
                return [layer - 1, col] // layer 代表层数, cols 记录每次循环的左右方向 (0:left, 1:right)
            } else if (target < current.data) {
                current = current.left
                cols.push(0)
            } else if (target > current.data) {
                current = current.right
                cols.push(1)
            }
        }
        return -1
    }

    // 广度
    this.breadth = function (callback) {
        let current = this.root
        let res = [current.data]
        const deep = (node) => {
            node.left && res.push(node.left.data)
            node.right && res.push(node.right.data)
            // 利用异步执行机制来交替打印左右树
            node.left && setTimeout(deep, 0, node.left)
            node.right && setTimeout(deep, 0, node.right)
            callback(res)
        }
        deep(current)
    }

    // 深度
    this.depth = function () {
        let current = this.root
        let res = [current.data]
        const deep = (node) => {
            node.left && res.push(node.left.data)
            node.left && deep(node.left)
            node.right && res.push(node.right.data)
            node.right && deep(node.right)
            return res
        }
        return deep(current)
    }
}

let bst = new BST()

let arr = [56, 22, 81, 10, 30, 77, 92]
arr.forEach(item => bst.insert(item))

const a = bst.preOrder() // 前序: [ 56, 22, 10, 30, 81, 77, 92 ]
const b = bst.inOrder() // 中序: [ 10, 22, 30, 56, 77, 81, 92 ]
const c = bst.postOrder() // 后续: [ 10, 30, 22, 77, 92, 81, 56 ]
console.log(a, b, c)
const d = bst.getMin() // 10
const e = bst.getMax() // 92
console.log(d, e)
const f = bst.find(92) // [2, 3]
console.log(f)
bst.breadth(data => { console.log(data) }) // [ 56, 22, 81, 10, 30, 77, 92 ]
const g = bst.depth() // [ 56, 22, 10, 30, 81, 77, 92 ]
console.log(g)

在这里插入图片描述

[56, 22, 81, 10, 30, 77, 92]
前序遍历:56 22 10 30 81 77 92
中序遍历:10 22 30 56 77 81 92
后序遍历:10 30 22 77 92 81 56
最小值:10
最大值:92

链表

function LinkedList() {
    // 辅助类 表示要加入链表的项
    let Node = function (element) {
        this.element = element
        this.next = null; // 指向链表中下一个节点项的指针
    }

    let length = 0
    let head = null

    // 向链表尾部添加一个新的项
    this.append = function (element) {
        let node = new Node(element),
            current

        if (head === null) { //链表为空,添加到首部
            head = node
        } else {
            current = head;
            //循环链表,直到找到最后一项
            while (current.next) {
                current = current.next
            }
            //找到最后一项,将其next赋为node,建立连接
            current.next = node
        }
        length++
    }
    // 向链表特定位置插入一个新的项
    this.insert = function (position, element) {
        //检查是否越界
        if (position >= 0 && position <= length) {
            let node = new Node(element),
                current = head,
                previous,
                index = 0

            if (position === 0) { //在第一个位置添加
                node.next = current
                head = node
            } else {
                while (index++ < position) {
                    previous = current
                    current = current.next
                }
                //通过改变指针,将node链接在previous和current之间
                node.next = current
                previous.next = node
            }
            length++;
            return true
        } else {
            return false
        }
    }
    // 从链表特定位置移除一项
    this.removeAt = function (position) {
        //检查是否越界
        if (position > -1 && position < length) {
            let current = head,
                previous,
                index = 0

            if (position === 0) { //移除第一项
                head = current.next
            } else {
                while (index++ < position) {
                    previous = current
                    current = current.next
                }
                //将previous与current的下一项链接起来,跳过current,从而移除它
                previous.next = current.next
            }
            length--
            return current.element
        } else {
            return null
        }
    }
    // 从链表中移除一项
    this.remove = function (element) {
        let index = this.indexOf(element)
        this.removeAt(index)
    }
    // 返回元素在链表中的索引,如果没有则返回-1
    this.indexOf = function (element) {
        let current = head,
            index = 0
        while (current) {
            if (current.element === element) {
                return index
            }
            index++
            current = current.next
        }
        return -1
    }
    // 判断链表是否为空
    this.isEmpty = function () {
        return length === 0
    }
    // 返回链表包含元素个数
    this.size = function () {
        return length
    }
    // 返回链表第一个元素
    this.getHead = function () {
        return head
    }
    // 只输出元素的值
    this.toString = function () {
        let current = head,
            string = ""
        while (current) {
            string += "," + current.element
            current = current.next
        }
        return string.slice(1)
    }
}

let list = new LinkedList()
for (let i = 0; i < 5; i++) { list.append(i) }
list.remove(3)
list.removeAt(3)
console.log(list.toString()) // 0,1,2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值