js 实现链表和树的结构

最近在学习es6
所以代码主要使用了es6的一些东西

链表的设计

我们设计链表包含两个类,一个是 Node 类用来表示节点,另一个事 LinkedList 类提供插入节点、删除节点等一些操作。

        /**
         * 一般的语言实现链表都需要指针来实现
         * 而js的引用类型本来就是按值引用的
         * 变量中保存的实质上是一个指向其对应对象的一个指针
         */
        class Node {        
            constructor(val) {
                this.val = val;
                this.next = null;
            }
        }
        class LinkedList {  //传入和返回都是Node类型,第一个元素下标0
            constructor(node) {   
                this.head = node;
                this.length = 1;
            }
            get isEmpty(){
                return !this.length;
            }
            append(node){   
                var lastNode=this.findAsIndex(this.length-1);
                lastNode.next=node;
                this.length++;
            }
            insert(index,node){   //在哪个元素之前插入
                var targetNode=this.findAsIndex(index-1);
                node.next=targetNode.next;
                targetNode.next=node;
            }
            remove(index){
                var preNode=this.findAsIndex(index-1);
                var nextNode=this.findAsIndex(index+1);
                preNode.next=nextNode;
            }
            findAsIndex(index){   
                if(index>this.length){
                    console.log('越界');
                    return
                }
                if(index===0){
                    return this.head;
                }
                var curNode=this.head; 
                while(index&&curNode){
                    index--;
                    curNode=curNode.next;
                }
                return curNode;
            }
            toString(){
                var curNode=this.head;
                var arr=[];
                var i=0;
                while(curNode){
                    arr[i++]=curNode.val;
                    curNode=curNode.next;
                }
                return arr.toString();
            }
        }
        let list=new LinkedList(new Node('a'));
        list.append(new Node('b'));
        list.append(new Node('d'));
        list.insert(2,new Node('c'));
        list.remove(1);
        console.log(list.toString())

队列简单的实现ES5版本

        function Queue(item) {
            this.items = item || [];
        }
        Queue.prototype = {
            constructor: Queue,
            enqueue: function (node) {
                return this.items.push(node)
            },
            dequeue: function (node) {
                return this.items.shift(node)
            },
            get size() {
                return this.items.length
            },
            get isEmpty() {
                return !this.items.length
            }
        }

        function LoopQueue() {
            Queue.call(this);
        }
        LoopQueue.prototype = Object.create( Queue.prototype)
        var loopQ = new LoopQueue();
        loopQ.enqueue('SkyRover')
        loopQ.enqueue('Even')
        loopQ.enqueue('Alice')
        console.log(loopQ)

在这里插入图片描述

树的基本概念

  • 结点
  • 结点的度
    结点所拥有的分支数目,如结点7的度为2
  • 叶子(终端结点)
  • 树的深度
    树中结点的最大层次称为树的深度,如上图树的深度为4
  • 森林
    m(m>=0)棵互不相交树的集合称为森林

二叉树

二叉树中的结点最多只能有两个子结点:一个是左侧子结点,另一个是右侧子结点。

二叉树的基本运算

  1. 创建一棵二叉树
  2. 显示一棵二叉树
  3. 按先序遍历(根、左、右)二叉树上所有结点
  4. 按中序遍历(左、根、右)二叉树上所有结点
  5. 按后序遍历(右、根、左)二叉树上所有结点
  6. 按层次遍历二叉树上所有结点
  7. 求二叉树叶子结点数目
  8. 求二叉树结点数目
  9. 求二叉树深度

二叉树性质

  1. 在二叉树的第i层上至多有 2^(i-1)个结点
  2. 深度为h的二叉树中至多有2^(h-1)个结点
  3. 对任意一棵二叉树T,如果其叶子结点数为n0,度为2的结点数为n2,则有n0=n2+1;
  4. 具有n个结点的完全二叉树的深度为log2n - 1
  5. 如果一棵有n个结点的完全二叉树(其深度为log2n - 1)的结点按层次(从第1层到log2n - 1层),每层从左到右,则对任一结点i(1<=i<=n)有:
    如果i等于1 结点i是根节点,无双亲;
    如果i>1在,则双亲结点是结点i/2;
    如果2i>n,则结点i无左侧子结点,该结点为叶子结点;否则其左侧子结点为2i;
    如果2i+1>n,则结点i无右侧子结点,该结点为叶子结点;否则其右侧子结点为2i+1;

具体实现

在这里插入图片描述

        class Node {
            constructor(key, left = null, right = null) {
                this.key = key;
                this.left = left;
                this.right = right;
            }
        }
        class BinarySearchTree {
            constructor(node) {
                this.root = node;
            }
            insert(newNode, node = this.root) {
                if (!this.root) {
                    this.root = newNode;
                } else {
                    if (newNode.key < node.key) {
                        if (node.left === null) {
                            node.left = newNode;
                        } else {
                            this.insert(newNode, node.left);
                        }
                    } else {
                        if (node.right === null) {
                            node.right = newNode
                        } else {
                            this.insert(newNode, node.right)
                        }
                    }
                }
            }
            preOrderTraverse(curNode = this.root) { //可以从指定结点进行
                if (!curNode) {
                    return
                }
                var arr = [];
                const preOrderTraverseNode = (node) => {
                    if (!node) {
                        return
                    }
                    arr.push(node.key)
                    preOrderTraverseNode(node.left);
                    preOrderTraverseNode(node.right);
                }
                preOrderTraverseNode(curNode);
                return arr;
            }
            inOrderTraverse(curNode = this.root) {
                if (!curNode) {
                    return
                }
                var arr = [];
                const inOrderTraverseNode = (node) => {
                    if (!node) {
                        return
                    }
                    inOrderTraverseNode(node.left);
                    arr.push(node.key)
                    inOrderTraverseNode(node.right);
                }
                inOrderTraverseNode(curNode);
                return arr;
            }
            postOrderTraverse(curNode = this.root) {
                if (!curNode) {
                    return
                }
                var arr = [];
                const postOrderTraverseNode = (node) => {
                    if (!node) {
                        return
                    }
                    postOrderTraverseNode(node.left);
                    postOrderTraverseNode(node.right);
                    arr.push(node.key)
                }
                postOrderTraverseNode(curNode);
                return arr;
            }
            minNode(node = this.root) {
                if (!node.left) {
                    return node.key;
                }
                return this.minNode(node.left);
            }
            maxNode(node = this.root) {
                if (!node.right) {
                    return node.key;
                }
                return this.maxNode(node.right);
            }
            search(key,curNode=this.root) {
                if(!curNode){
                    return false
                }
                if(key===curNode.key){
                    return curNode
                }
                return this.search(key,key<curNode.key?curNode.left:curNode.right)
            }

        }
        const tree = new BinarySearchTree(new Node(11));
        tree.insert(new Node(15))
        tree.insert(new Node(7))
        tree.insert(new Node(5))
        tree.insert(new Node(3))
        tree.insert(new Node(9))
        tree.insert(new Node(8))
        tree.insert(new Node(10))
        tree.insert(new Node(13))
        tree.insert(new Node(12))
        tree.insert(new Node(14))
        tree.insert(new Node(20))
        tree.insert(new Node(18))
        tree.insert(new Node(25))
        console.log(tree.preOrderTraverse())
        console.log(tree.inOrderTraverse())
        console.log(tree.postOrderTraverse())
        console.log(tree.minNode());
        console.log(tree.maxNode());
        console.log(tree.search(9));
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值