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&¤t.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 } }