javascript-数据结构与算法实现

2018-01-23

本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。

声明: 本博客欢迎转发,但请保留原作者信息!
github地址:atanx
新浪微博:@蜀山掌门V
QQ:365039667
博客地址:江斌的博客
内容仅供学习参考,如有不当引用,请告知博主。

[toc]

数据结构

队列

var Queue = function(){
    this._data = [];
}

Queue.prototype.is_empty = function(){
    return this._data.length == 0;
}

Queue.prototype.enqueue = function(d){
    return this._data.push(d);
}

Queue.prototype.dequeue = function(){
    if(this.is_empty()){
        throw 'queue is empty!';
    }
    else{
        d = this._data.splice(0,1);
    }
    return d[0];
}

Queue.prototype.size = function(){
    return this._data.length;
}

var queue = new Queue();
for(var i = 0; i<10; i++){
    queue.enqueue(i);
}

while(!queue.is_empty()){
    console.log(queue.dequeue());
}


var Stack = function(){
    this._data = [];
}

Stack.prototype.is_empty = function(){
    return this._data.length==0;
}

Stack.prototype.push = function(d){
    this._data.push(d);
}

Stack.prototype.pop = function(){
    if(this.is_empty()){
        throw "stack is empty!"
    }
    return this._data.pop();

}

Stack.prototype.peek = function(){ 
    return this._data[this._data.length]; 
}

Stack.prototype.size = function(){
    return this._data.length;
}


// 监测括号是否平衡
var check_brace = function(str){
    var opens = '([{';
    var closes = ')]}';

    var stack = new Stack();
    var blanced = true;

    for(var i = 0; i<str.length; i++){
        var s = str[i];
        if(opens.indexOf(s)>=0){ 
            stack.push(str[i]);
        }
        if(closes.indexOf(s)>=0){
            if(stack.is_empty()){
                blanced = false;
                break;
            }
            else{
                j = stack.pop();
                if (opens.indexOf(j) != closes.indexOf(s)){
                    blanced = false;
                    break;
                }
                                
            }
        }

     }
     if(!stack.is_empty()){
         blanced = false;
     }
    return blanced;
}


// 十进制转二进制
var dec2bin= function(dec){
    var stack = new Stack();
    var c = dec;
    while(c>0){
        var a = c % 2;
        c = Math.floor(c / 2);
        stack.push(a);
    }
    binstr = '';
    while(!stack.is_empty()){
        binstr += stack.pop();
    }
    return binstr;
}


// 后缀表达式
var infix2postfix = function(infix){ 
    var a={};
    a['*']=3;
    a['/']=3;
    a['+']=2;
    a['-']=2;
    a['(']=1;
    var stack=new Stack();
    post='';

    for(var i = 0; i<infix.length; i++){ //对于每一个字符
        var s = infix[i];
       
        if (!a.hasOwnProperty(s) &&  s!=')'){ //非运算符
            post+=s;
        }
        else if(s=='('){  // 左括号
            stack.push(s);
        }
        else if (s==')'){ // 右括号 
            t=stack.pop(); 
            console.log(stack);
            console.log(t);
            while (t!='('){ 
                post+= ' ' + t;
                t=stack.pop(); 
            }
        }
        else{  // * / + - 
            while (!stack.is_empty() && a[s]<=a[stack.peek()]){ 
                post+=stack.pop();
            }  
            stack.push(s);
            post += ' ';
        }  
        console.log(s,stack._data) ;     
    }

    while (!stack.is_empty()){
        post+= ' ' + stack.pop();
    }

    return post;
}

// 后缀表达式计算
var postfixExp = function(postfix){
    var stack = new Stack();
    var post_list = postfix.split(' ');
    for(var i = 0; i<post_list.length; i++){
        var s  =post_list[i];
        if('+-*/'.indexOf(s) == -1){ 
            stack.push(s);
        }
        else{
            var a = stack.pop();
            var b = stack.pop();
            var result = math(s, b, a); 
            stack.push(result);
        }
    }
    return stack.pop();
}

var math = function(op, b, a){
    if(op=='+'){
        return parseFloat(b) + parseFloat(a);
    }
    if(op=='-'){
        return  parseFloat(b) - parseFloat(a);
    } 
    if(op=='*'){
        return parseFloat(b) * parseFloat(a);
    }
    if(op=='/'){
        return  parseFloat(b) / parseFloat(a);
    }
}

var p = infix2postfix('(12+2)/(10-3.6)');
postfixExp(p);

链表

var Node = function(element){
    this.element = element;
    this.next = null;
}

var LinkedList = function(){
    this.head = new Node('head'); 
}

LinkedList.prototype.find = function(item){
    var currNode = this.head;
    while(currNode.element != item){
        currNode = currNode.next;
    }
    return currNode;
}

LinkedList.prototype.insert = function(newElement, item){
    var newNode = new Node(newElement);
    var current = this.find(item);
    newNode.next = current.next;
    current.next = newNode;
}
LinkedList.prototype.display = function(){
    var s = '';
    var currNode = this.head;
    while(currNode.next != null){
        s += " "+currNode.element;
        
    }
    
    return s;
}

var cities = new LinkedList();
cities.insert('北京', 'head');
cities.insert('上海', '北京');

cities.insert('济南', '北京');
var arr = cities.display();
console.log(arr);


/** 树形结构节点 */
var Node = function(element){
    this.element = element;
    this._parent = null;
    this._children = [];
}
Node.prototype.is_leaf = function(){
    return this._children.length == 0;
}
Node.prototype.is_root = function(){
    return this._parent == null;
}
Node.prototype.deepth = function(){

}

/** 树状结构 */
var Tree = function(){
    this.nodes = [];
    this.root = null; 
}

Tree.prototype.add_root = function(node){
    this.root = node;
    this.nodes.push(node);
    return this.root;
}
Tree.prototype.append_child = function(parent_node, child_node){
    parent_node._children.push(child_node);
    child_node._parent = parent_node;
    this.nodes.push(child_node);
    return {parent: parent_node, child: child_node};
}
Tree.prototype.display = function(){
    var display = function(node, deepth){
        var s = '';
        for(var i = 0; i<deepth; i++){ 
            s = '\t'+ s; 
        }
        s =  s + node.element;
        console.log(s);
        for (var i = 0; i<node._children.length; i++){
            display(node._children[i], deepth+1);
        }

    }
    display(this.root, 0);
}

Tree.prototype.deepth = function(){
    var deepth = 0;
    for(var i = 0; i<this.nodes.length; i++){
            var node = this.nodes[i];

            if(!node.is_leaf()){
                continue;
            }

            var tmp_deepth = 1;
            var p = node._parent;
            while(p!=null){
                tmp_deepth += 1;
                p = p._parent;
            }
            if(tmp_deepth>deepth){
                deepth = tmp_deepth;
            }

      }

    return deepth;
}


var tree = new Tree();
var root = tree.add_root(new Node('A'));
r = tree.append_child(root, new Node('B'));
rc = tree.append_child(root, new Node('C'));
r = tree.append_child(rc.child, new Node('E'));
r = tree.append_child(rc.child, new Node('F'));
r = tree.append_child(root, new Node('D'));

tree.display();

/***********************************************************************************
 * Javascript实现dijkstra最短路径算法。
 * 作者:江斌
 ***********************************************************************************/

/*** 图数据结构。
 * @graph: Graph类型
 * @src_node_name: string 起始节点名称
 * @dist_node_name: string 目标节点名称
 */
var Graph = function () {
    this.nodes = {};
    this.edges = {};
    this.distances = {};

    this.add_node = function (node) {
        this.nodes[node.name] = node;
    };
    this._add_edge = function (from_node_name, to_node_name, distance) {
        if (this.edges[from_node_name] == undefined) {
            this.edges[from_node_name] = []
        }
        this.edges[from_node_name].push(to_node_name);
        this.distances[from_node_name + '_' + to_node_name] = distance;
    };
    this.add_edge = function (from_node_name, to_node_name, distance, bipartite = true) {

        this._add_edge(from_node_name, to_node_name, distance);
        if (bipartite) {
            this._add_edge(to_node_name, from_node_name, distance);
        }
    };
};

/**
 * 图节点
 * @param name string 节点名称。
 */
var Node = function (name) {
    this.distance = Infinity;
    this.predecessor = null;
    this.name = name;

    // this.set_distance = function(distance){
    //     this.distance = distance;
    // };
    //
    // this.get_distance = function(){
    //     return this.distance;
    // };
    //
    // this.set_predecessor = function(node){
    //     this.predecessor = node;
    // };
    //
    // this.get_predecessor = function(){
    //     return this.predecessor;
    // }
};

var dijkstra = function (graph, src_node_name, dist_node_name) {
    graph.nodes[src_node_name].distance = 0;
    var permanent = new Set();
    var temp = new Set();
    temp.add(src_node_name);
    while (temp.size > 0) {
        var min_node_name = null;
        temp.forEach(function (d) {
            if (min_node_name == null) {
                min_node_name = d;
            }
            else if (graph.nodes[d].distance < graph.nodes[min_node_name].distance) {
                min_node_name = d;
            }
        });

        temp.delete(min_node_name);
        permanent.add(min_node_name);

        var current_distance = graph.nodes[min_node_name].distance;
        for (var i = 0; i < graph.edges[min_node_name].length; i++) {
            var neighbour = graph.edges[min_node_name][i];
            var new_distance = current_distance + graph.distances[min_node_name + '_' + neighbour];
            if (!permanent.has(neighbour) && new_distance < graph.nodes[neighbour].distance) {
                graph.nodes[neighbour].distance = new_distance;
                graph.nodes[neighbour].predecessor = min_node_name;
                temp.add(neighbour); //
            }
        }

    }
    print_path(graph, dist_node_name);
};

function print_path(graph, dist) {
    var current = dist;
    var path = [dist];
    while (graph.nodes[current].predecessor != null) {
        path.push(graph.nodes[current].predecessor);
        current = graph.nodes[current].predecessor;
    }
    console.log(path.reverse().join('->'));
}

function run() {
    var g = new Graph();

    g.add_node(new Node('A'));
    g.add_node(new Node('B'));
    g.add_node(new Node('C'));
    g.add_node(new Node('D'));
    g.add_node(new Node('E'));
    g.add_node(new Node('F'));

    g.add_edge('A', 'B', 10);
    g.add_edge('A', 'C', 15);
    g.add_edge('A', 'E', 30);
    g.add_edge('B', 'D', 50);
    g.add_edge('B', 'E', 14);
    g.add_edge('C', 'D', 12);
    g.add_edge('C', 'E', 12);
    g.add_edge('D', 'F', 10);
    g.add_edge('E', 'F', 20);


    dijkstra(g, 'A', 'F');
}

run();

算法

排序

冒泡排序

选择排序

var select_sort = function(arr){
    for(var i = 0; i< arr.length; i++){
        var index = i;
        for(var j=i+1; j<arr.length; j++ ){
            if(arr[j]<arr[index]){
                index = j;
            }
        }

        if(index == i){
            continue;
        }
        else{
            var tmp = arr[i];
            arr[i] = arr[index];
            arr[index] = tmp;
        }
    }
    return arr;
}

插入排序

快速排序

var quick_sort = function(arr, start, end){
   if(start>=end){
       return;
   }
    var low_idx  = start;
    var high_idx = end;
    var base = arr[start];
    while(low_idx < high_idx){
        while(low_idx<high_idx && arr[high_idx]>=base){
            high_idx--;
        }
        if(low_idx < high_idx){
            arr[low_idx] = arr[high_idx];
            low_idx++;
        }

        while(low_idx<high_idx && arr[low_idx] < base){
            low_idx++;
        }
        if(low_idx < high_idx){
            arr[high_idx] = arr[low_idx];
            high_idx--;
        }
    } 
    arr[low_idx] = base;
    console.log(low_idx, high_idx,'base='+base, arr);
    quick_sort(arr, start, low_idx-1);
    quick_sort(arr, low_idx+1, end);
}

堆排序


/*************************************************
*
* 打印堆
*
*************************************************/

function mi2(num){
    var m = 0;
    while(num>Math.pow(2,m)){
        m = m + 1;
    }
    return m;
}
function print_heap(heap_arr){
    var idx_arr = [];
    for(var i = 0; i< heap_arr.length; i++){
        idx_arr.push([i]); 
    }
    for(var i = Math.floor(idx_arr.length/2); i>=0; i--){
        var left = 2*i+1;
        var right = 2*i+2;
        if(left<idx_arr.length){
            idx_arr[i] = idx_arr[left].concat(idx_arr[i]);
            idx_arr[left]= null;
        }
        if(right<idx_arr.length){
            idx_arr[i] = idx_arr[i].concat(idx_arr[right]);
            idx_arr[right]= null;
        }
    }
    idx_arr =  idx_arr[0]; 

    
    var tmp_arr = [];  
    var height = mi2(heap_arr.length);
    var s = '';
    for(var level = 0; level<height; level++){
        var tmp_arr = [];
        for(var j=0; j<heap_arr.length; j++){
            tmp_arr.push('   ');
        }

        var start = Math.pow(2, level) - 1;
        var end = Math.pow(2, level+1) -2;
        for(var i = start; i<=end; i++){
            var pos = idx_arr.indexOf(i);
            tmp_arr[pos] = heap_arr[i];
        }

        s += tmp_arr.join(' ')+'\n';
       }
       console.log(s);
};
 


function HeapAdjust(arr,s,length){                // 使用调整大顶堆进行排序,将s到m之间的数值调整为大顶堆!
           var max_idx = s;                  // 将大顶堆顶值赋值给max;
           var left = 2*s+1;
           var right = 2*s+2;
           if(left < length && arr[left]>arr[max_idx]){
               max_idx = left;
           }
           if(right < length && arr[right]>arr[max_idx]){
               max_idx = right;
           }
           if(max_idx!=s){ 
              swap(arr, s, max_idx);  
              HeapAdjust(arr,max_idx,length);
              
           }
           else{ 
              return;
           }
        }

function HeapSort(arr)
{
    print_heap(arr);
   for(var i=Math.floor(arr.length/2); i>=0; i--){//首先构造一个标准的大堆顶,只需要便利二叉树一半的节点,就能够把大堆顶构造出来 
       HeapAdjust(arr, i, arr.length);
   }

   for(var i=arr.length-1; i>0; i--){//构造完之后 把堆顶的值和最后一个互换,然后 排除最后一个继续进行打造大堆顶!
       swap(arr, 0, i);  
       HeapAdjust(arr, 0, i); 
      console.log( 'i='+i);
      print_heap(arr);
   }
}
function swap(arr, i, j){
   var temp = arr[i];
   arr[i] = arr[j];
   arr[j] = temp;
}

var random = function(n){
    var a = [];
    while(n>0){
        a.push(Math.round(Math.random()*100));
        n--;
    }
    return a;
}
//arr = [5,3,7,9,2,6,8];
// arr = random(10);
arr = [51, 94, 64, 10, 27, 29, 88, 21, 16, 98];
HeapSort(arr); 

非递归实现

 
function mi2(num){
    var m = 0;
    while(num>Math.pow(2,m)){
        m = m + 1;
    }
    return m;
}
function print_heap(heap_arr){
    var idx_arr = [];
    for(var i = 0; i< heap_arr.length; i++){
        idx_arr.push([i]); 
    }
    for(var i = Math.floor(idx_arr.length/2); i>=0; i--){
        var left = 2*i+1;
        var right = 2*i+2;
        if(left<idx_arr.length){
            idx_arr[i] = idx_arr[left].concat(idx_arr[i]);
            idx_arr[left]= null;
        }
        if(right<idx_arr.length){
            idx_arr[i] = idx_arr[i].concat(idx_arr[right]);
            idx_arr[right]= null;
        }
    }
    idx_arr =  idx_arr[0]; 

    
    var tmp_arr = [];  
    var height = mi2(heap_arr.length);
    var s = '';
    for(var level = 0; level<height; level++){
        var tmp_arr = [];
        for(var j=0; j<heap_arr.length; j++){
            tmp_arr.push('   ');
        }

        var start = Math.pow(2, level) - 1;
        var end = Math.pow(2, level+1) -2;
        for(var i = start; i<=end; i++){
            var pos = idx_arr.indexOf(i);
            tmp_arr[pos] = heap_arr[i];
        }

        s += tmp_arr.join(' ')+'\n';
       }
       console.log(s);
};


/***
* l:数组
* s: 堆顶在数组中的下标
* m:堆的长度
*/
function HeapAdjust(l,s,m){//使用调整大顶堆进行排序,将s到m之间的数值调整为大顶堆!
   var temp=l[s];//将大顶堆顶值负值给temp; 
   for(var j=2*s+1;j<m;j=2*j+1) 
   {
       //if(j<m&&l[j]<l[j+1]) // j修改为j+1
       if(j+1<m&&l[j]<l[j+1])
           ++j;
       if(temp>=l[j])//如果堆顶的值大于当前j下标的值,就不用再找了。跳出循环
         break;
       l[s]=l[j];//小于j下标的值,就把l[j]复制给l[s]
       s=j;//s就指向当前j的位置,为下步把顶值赋值到这个位置做准备(循环完之前,先不赋值)
       }
      l[s]=temp;//最后赋值给l[s](s指向现在找到的最大的大堆顶的值)
   }
function HeapSort(l)
{
   //for(var i=l.length/2;i>=0;i--) // 增加取整
   for(var i=Math.floor(l.length/2);i>=0;i--) 
       HeapAdjust(l,i,l.length);  
   for(var i=l.length;i>0;i--){//构造完之后 把堆顶的值和最后一个互换,然后 排除最后一个继续进行打造大堆顶! 
       swap(l,0,i-1);
       print_heap(l);
       //HeapAdjust(l,0,i-2);  // i-2修改为i-1
       HeapAdjust(l,0,i-1); 
   }
}
function swap(l,i,j){
   var temp=l[i];
   l[i]=l[j];
   l[j]=temp;
}

//arr = [51, 94, 64, 10, 27, 29, 88, 21, 16, 98];
arr = [94, 64, 10, 27, 29, 88, 21, 16, 98];
HeapSort(arr);

希尔排序

归并排序

查找



章节列表