js二叉搜索树和图

 

 //封装二分搜索树
    function BinarySerachTree(){
        function Node(key){
            this.key=key
            this.left=null
            this.right=null
        }

        //属性
        this.root=null

        //方法
        //插入数据
        BinarySerachTree.prototype.insert=function(key){
            //1.判断 key创建节点
            var newNode=new Node(key)

            //2.判断接节点是否有值
            if(this.root==null){
                this.root=newNode
            }else{
               this.insertNode(this.root,newNode)
            }
        }

        BinarySerachTree.prototype.insertNode=function(node,newNode){
           if(newNode.key<node.key){  //向左查找
                if(node.left==null){
                    node.left=newNode
                }else{
                    this.insertNode(node.left,newNode)
                }
           }else{  //向右查找
              if(node.right==null){
                  node.right=newNode
              }else{
                  this.insertNode(node.right,newNode)
              }
           }
        }

        //树的遍历
        //1.先序遍历
        BinarySerachTree.prototype.preOrderTraversal=function(handler){
            this.preOrderTraversalNode(this.root,handler)

        }

        BinarySerachTree.prototype.preOrderTraversalNode=function(node,handler){
           if(node!=null){
               //1.处理经过的节点
               handler(node.key)
               
               //2.处理经过节点的左子节点
               this.preOrderTraversalNode(node.left,handler)

               //3.处理经过的右子节点
               this.preOrderTraversalNode(node.right,handler)
           }
          
        }
    
       //2.中序遍历
       BinarySerachTree.prototype.midOrderTraversal=function(handler){
           this.midOrderTraversalNode(this.root,handler)
       }

       BinarySerachTree.prototype.midOrderTraversalNode=function(node,handler){
           if(node!=null){
               //1.处理左子树中的节点
               this.midOrderTraversalNode(node.left,handler)

               //2.处理节点
               handler(node.key)

               //3.处理右字数中的节点
               this.midOrderTraversalNode(node.right,handler)

           }
       }

       //3.后序遍历
       BinarySerachTree.prototype.postOrderTraversal=function(handler){
           this.postOrderTraversalNode(this.root,handler)
       }

       BinarySerachTree.prototype.postOrderTraversalNode=function(node,handler){
          if(node!==null){
              //1.查找左子树中的节点
              this.postOrderTraversalNode(node.left,handler)

              //2.查找右子树中的节点
              this.postOrderTraversalNode(node.right,handler)

            //3.处理节点
            handler(node.key)
              
          }
       }

       //寻找最大值
       BinarySerachTree.prototype.max=function(){
          //1.获取根节点
          var node=this.root

          //2.依次向右不断的查找,直到节点为 null
          var key=null
          while(node!=null){
              key=node.key
              node=node.right
          }
          return key
       }

       //2.寻找最小值
       BinarySerachTree.prototype.min=function(){
         //1.获取根节点
         var node=this.root

         //2.依次向左不断的查找,直到节点为 null
         var key=null
         while(node!=null){
             key=node.key
             node=node.left
         }
         return key
       }
    
       //3.搜索特定的值
       BinarySerachTree.prototype.search=function(key){
           return this.searchNode(this.root,key)
       }

       //递归实现
       BinarySerachTree.prototype.searchNode=function(node,key){
           //1.如果传入的 node 为 null ,就推出递归
           if(node==null) return false

           //2.判断 node 节点的值和传入的key 大小
           if(node.key>key){  //传入的 key 较小,向左继续查找
              return this.searchNode(node.left,key)
           }else if(node.key<key){ //传入的 key较大,向右边继续查找
              return this.searchNode(node.right,key)
           }else{  //2.3相同,说明找到了 key
              return true
           }
       }
       
       //循环实现
       BinarySerachTree.prototype.search1=function(key){
           //1.获取根节点
           var node=this.root

           //2.循环来搜索 key
           while(node!=null){
              if(key<node.key){
                node=node.left
              }else if(key>node.key){
                node=node.right
              }else{
                  return true
              }
           }
           return false 
       }
    
       //删除节点
       BinarySerachTree.prototype.remove=function(key){
          //1.寻找要删除的节点
          //1.1定义变量,保存一些信息
          var current=this.root
          var parent=null
          var isLeftChild=true

          //1.2开始寻找删除的节点
          while(current.key!=key){
              parent=current
              if(key<current.key){
                  isLeftChild=true
                  current=current.left
              }else {
                 isLeftChild=false
                 current=current.right
              }
              //某种情况,已经找到了最后的节点,依然没有找到==key
              if(current==null) return false
          }

          //2.根据对应的情况删除节点
          //2.1删除的节点是叶子节点(没有子节点)
           if(current.left==null&&current.right==null){
               if(current==this.root) this.root=null
               else if(isLeftChild){
                   parent.left=null
               }else{
                   parent.right=null
               }
           }
          //2.2删除的节点有一个叶子节点
          else if(current.right==null){
              if(current==this.root){
                  this.root=current.left
              }else if(isLeftChild){
                  parent.left=current.left
              }else{
                  parent.right=current.left
              }
          }else if(current.left==null){
              if(current==this.root){
                  this.root==current.right
              }else if(isLeftChild){
                  parent.left=current.right
              }else{
                  parent.right=current.right
              }
          }

          //2.3删除的节点有两个节点
         else{
             //1.获取后继节点
             var successor=this.getSuccessor(current)

             //2.判断是否根节点
             if(current==this.root) this.root=successor
             else if(isLeftChild) parent.left=successor
             else parent.right=successor

             //3.将删除节点的左子树= current.left
             successor.left=current.left
             
         }
       }
       //找后继的方法
       BinarySerachTree.prototype.getSuccessor=function(delNode){
           //1.定义变量,保存找到的后继
           var successor=delNode
           var current=delNode.right
           var successorParent=delNode

           //2.循环查找
           while(current!=null){
               successorParent=successor
               successor=current
               current=current.left
           }

           //3.判断寻找到的后继节点是否直接就是delNode的 right节点
           if(successor!=delNode.right){
               successorParent.left=successorParent.right
               successor.right=delNode.right   
           } 
           return successor
       }
    }
    


    //测试代码
    var bst=new BinarySerachTree()

    //2.插入数据
    bst.insert(11)
    bst.insert(7)
    bst.insert(15)
    bst.insert(5)
    bst.insert(3)
    bst.insert(9)
    bst.insert(8)
    bst.insert(10)
    bst.insert(13)
    bst.insert(12)
    bst.insert(20)
    bst.insert(18)
    bst.insert(25)
    bst.insert(6)

    //3.测试线序遍历
    // var resultString=''
    // bst.preOrderTraversal(function(key){
    //     resultString+=key+" "
    // })
    //alert(resultString)

    //2.测试中序遍历
    // resultString=""
    // bst.midOrderTraversal(function(key){
    //     resultString+=key +" "
    // })
    // alert(resultString)

    //3.测试后序遍历
    resultString=""
    bst.postOrderTraversal(function(key){
        resultString+=key +" "
    })
    // alert(resultString)

    // alert(bst.max())
    // alert(bst.min())

    //5.测试搜索方法
    // alert(bst.search(25))
    // alert(bst.search(24))
    // alert(bst.search(2))

    // alert(bst.search1(25))
    // alert(bst.search1(24))
    // alert(bst.search1(2))

    bst.remove(9)
    bst.remove(7)
    bst.remove(15)

    resultString=""
    bst.postOrderTraversal(function(key){
        resultString+=key+" "
    })

    alert(resultString)

  红黑树的特点:

 图的特点:

 图:

    //封装图结构
    function Graph(){
        //属性  顶点(数组) /边(字典)
        this.vertexes=[] //顶点
        this.edges=new Dictionary()  //边

        //方法
        //1.添加顶点的方法
        Graph.prototype.addVertex=function(v){
            this.vertexes.push(v)
            this.edges.set(v,[])
        }
       
        //2.添加边的方法
        Graph.prototype.addEdge=function(v1,v2){
           this.edges.get(v1).push(v2)
           this.edges.get(v1).push(v1)
        }

        //三.实现toString方法:转换为邻接表形式
        Graph.prototype.toString = function (){
        //1.定义字符串,保存最终结果
        let resultString = ""

        //2.遍历所有的顶点以及顶点对应的边
        for (let i = 0; i < this.vertexes.length; i++) {//遍历所有顶点
          resultString += this.vertexes[i] + '-->'
          let vEdges = this.edges.get(this.vertexes[i])
          for (let j = 0; j < vEdges.length; j++) {//遍历字典中每个顶点对应的数组
            resultString += vEdges[j] + '  ';
          }
          resultString += '\n'
        }
        return resultString
      }
    
        //初始化状态颜色
        Graph.prototype.initializeColor=function(){
            var colors=[]
            for(var i=0;i<this.vertexes.length;i++){
                colors[this.vertexes[i]]='white'
            }
            return colors
        }   

        //实现广度优先搜索
        Graph.prototype.bfs=function(initV,handler){
          //1.初始化颜色
          var colors=this.initializeColor()

          //2.创建队列
          var queue=new Queue()

          //3.将顶点加入到队列中
          queue.enqueue(initV)

          //4.循环从队列中取出元素
          while(!queue.isEmpty()){
              //4.1从队列中取出一个顶点
              var v=queue.dequeue()

              //4.2获取和顶点相连的另外顶点
              var vList=this.edges.get(v)

              //4.3将 v 的颜色设置成灰色
              colors[v]='gray'

              //4.4遍历所有的顶点,并且加入到队列中
              for(var i=0;i<vList.length;i++){
                  var e=vList[i]
                  if(colors[e]=='white'){
                      colors[e]='gray'
                      queue.enqueue(e)
                  }
              }

              //4.5 v已经被探测,并且访问
              handler(v)

              //4.6 将顶点设置为黑色
              colors[v] = 'black'
          }
        }
    
        //深度优先搜索(DFS)
        Graph.prototype.dfs=function(initV,handler){
            //1.初始化颜色
            var colors=this.initializeColor()

            //2.从某个顶点开始依次递归访问
            this.dfsVisit(initV,colors,handler)
        }
        Graph.prototype.dfsVisit=function(v,colors,handler){
            //1.将颜色设置为灰色
            colors[v]='gray'

            //2.处理v 顶点
            handler(v)

            //3.访问 v 相邻的顶点
            var vList=this.edges.get(v)
            for(var i=0;i<vList.length;i++){
                var e=vList[i]
                if(colors[e]=='white'){
                    this.dfsVisit(e,colors,handler)
                }
            }

            //4.将 v 设置成黑色
            colors[v]='black'
        }
    }

    //测试代码
    var graph=new Graph()
    //2.添加顶点
    var myVertexes=['A','B','C','D','E','F','G','H','I']
    //g.vertexes=myVertexes
    for(var i=0;i<myVertexes.length;i++){
        graph.addVertex(myVertexes[i])
    }
   
   //3.添加边
   graph.addEdge('A', 'B')
    graph.addEdge('A', 'C')
    graph.addEdge('A', 'D')
    graph.addEdge('C', 'D')
    graph.addEdge('C', 'G')
    graph.addEdge('D', 'G')
    graph.addEdge('D', 'H')
    graph.addEdge('B', 'E')
    graph.addEdge('B', 'F')
    graph.addEdge('E', 'I')

    //alert(graph)
    //console.log(graph.toString());

    //5.测试bfs
    // var result=''
    // graph.bfs(graph.vertexes[0],function(v){
    //     result+=v + ' '
    // })
    // alert(result)

    //6.测试 dfs
    result=''
    graph.dfs(graph.vertexes[0],function(v){
        result+= v+'  '
    })
    alert(result)
       //封装字典类
function Dictionary(){
  //字典属性
  this.items = {}

  //字典操作方法
  //一.在字典中添加键值对
  Dictionary.prototype.set = function(key, value){
    this.items[key] = value
  }

  //二.判断字典中是否有某个key
  Dictionary.prototype.has = function(key){
    return this.items.hasOwnProperty(key)
  }

  //三.从字典中移除元素
  Dictionary.prototype.remove = function(key){
    //1.判断字典中是否有这个key
    if(!this.has(key)) return false

    //2.从字典中删除key
    delete this.items[key]
    return true
  }

  //四.根据key获取value
  Dictionary.prototype.get = function(key){
    return this.has(key) ? this.items[key] : undefined
  }

  //五.获取所有keys
  Dictionary.prototype.keys = function(){
    return Object.keys(this.items)
  }

  //六.size方法
  Dictionary.prototype.keys = function(){
    return this.keys().length
  }

  //七.clear方法
  Dictionary.prototype.clear = function(){
    this.items = {}
  }
}

   // 基于数组封装队列类
function Queue() {
    // 属性
      this.items = []
    // 方法
    // 1.将元素加入到队列中
    Queue.prototype.enqueue = element => {
      this.items.push(element)
    }

    // 2.从队列中删除前端元素
    Queue.prototype.dequeue = () => {
      return this.items.shift()
    }

    // 3.查看前端的元素
    Queue.prototype.front = () => {
      return this.items[0]
    }

    // 4.查看队列是否为空
    Queue.prototype.isEmpty = () => {
      return this.items.length == 0;
    }

    // 5.查看队列中元素的个数
    Queue.prototype.size = () => {
      return this.items.length
    }

    // 6.toString方法
    Queue.prototype.toString = () => {
      let resultString = ''
        for (let i of this.items){
          resultString += i + ' '
        }
        return resultString
      }
    }

  

   

posted @ 2020-11-05 22:11  石shi  阅读(132)  评论(0编辑  收藏  举报