JavaScript数据结构

2019-02-27  本文已影响0人  zhoulh_cn

数组

数组实现

  1. 创建和初始化数组
var daysOfWeek=[];
daysOfWeek=['Sunday', 'Monday', 'Tuesday', 'Wednesday','Thursday', 'Friday', 'Saturday'];
  1. 访问和迭代数组
for (var i=0;i<daysOfWeek.length;i++){
    console.log(daysOfWeek[i]);
}
  1. 添加元素
//尾添加
numbers.push(12, 13);
//or
numbers[numbers.length]=10;
//首添加
numbers.unshift(-4, -3);
//or
for(var i=numbers.length;i>0;i--){
    numbers[i]=numbers[i-1];
}
numbers[0]=-1;
  1. 删除元素
//尾删除
numbers.pop();
//or
numbers.length=numbers.length-1;
//首删除
numbers.shift();
//or
for(var i=0;i<numbers.length;i++){
    numbers[i]=numbers[i+1];
}
numbers.length=numbers.length-1;
  1. 在任意位置添加和删除元素
//添加
numbers.splice(5,0,2,3,4);
//删除
numbers.splice(5,3);

JavaScript数组的其他方法

  1. 数组合并
var zero=0;
var positiveNumbers=[1,2,3];
var negativeNumbers=[-3,-2,-1];
var numbers=negativeNumbers.concat(zero, positiveNumbers);
  1. 迭代器函数
var isEven=function(item){
   return (x%2==0)?true:false;
}
//every,每一项返回true时,整体返回true
numbers.every(isEven);
//some,任意一项返回true,整体返回true
numbers.some(isEven);
//filter,整体返回由返回值为true的项组成的数组
var evenNumbers=numbers.filter(isEven);
//map,整体返回由返回值组成的数组
var myMap=numbers.map(isEven);
//reduce,整体返回叠加的值
numbers.reduce(function(previous, current, index){
   return previous + current;
});
//forEach,对数组每一项执行传入函数
numbers.forEach(function(x){
   console.log((x % 2 == 0));
});



栈(LIFO)

栈实现

function Stack(){
    let items=[];
    //向栈添加元素
    this.push=function(element){
        items.push(element);
    };
    //从栈移除元素
    this.pop=function(){
        return items.pop();
    };
    //查看栈顶元素
    this.peek=function(){
        return items[items.length-1];
    };
    //检查栈是否为空
    this.isEmpty=function(){
        return items.length==0;
    };
    this.size=function(){
        return items.length;
    };
    //清空和打印栈元素
    this.clear=function(){
        items=[];
    };
    this.print=function(){
        console.log(items.toString());
    };
}
//使用Stack类
let stack=new Stack();

ECMAScript 6 实现Stack 类

  1. ES6声明Stack类
class Stack{
    constructor(){
        this.items=[];
    }
    push(element){
        this.items.push(element);
    }
    //其他方法
}

队列(FIFO)

队列实现

function Queue(){
    let items=[];
    //向队列添加元素
    this.enqueue=function(element){
        items.push(element);
    };
    //从队列移除元素
    this.dequeue=function(){
        return items.shift();
    };
    //查看队列头元素
    this.front=function(){
        return items[0];
    };
    //检查队列是否为空
    this.isEmpty=function(){
        return items.length == 0;
    };
    this.size=function(){
        return items.length;
    };
    //打印队列元素
    this.print=function(){
        console.log(items.toString());
    };
}
//使用Queue类
let queue=new Queue();



链表

数组的缺点:

  1. 大小固定
  2. 移动数据成本高
  3. 数据存储需要连续的空间

链表的缺点:

  1. 获取数据成本高

实现单向链表

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);
        let current;
        //空链表
        if(head===null){
            head=node;
        }else{
            current=head;
            while(current.next){
                current=current.next;
            }
            current.next=node;
        }
        length++;
    };
    this.insert=function(position,element){
        //检查越界
        if(position>=0&&position<=length){
            let node=new Node(element);
            let current=head;
            let previous;
            let index=0;
            if(position===0){
                node.next=current;
                head=node;
            }else{
                while(index<position){
                    previous=current;
                    current=current.next;
                    index++;
                }
                node.next=current;
                previous.next=node;
            }
            length++;
            return true;
        }else{
            return false;
        }
    };
    this.removeAt=function(position){
        //检查越界
        if(position>=0&&position<length){
            let current=head;
            let previous;
            index=0;
            if(position===0){
                head=current.next;
            }else{
                while(index<position){
                    previous=current;
                    current=current.next;
                    index++;
                }
                previous.next=current.next;
            }
            length--;
            return current.element;
        }else{
            return null;
        }
    };
    this.indexOf=function(element){
        let current=head;
        let index=0;
        while(current){
            if(element===current.element){
                return index;
            }
            index++;
            current=current.next;
        }
        return -1;
    };
    this.remove=function(element){
        let index=this.indexOf(element);
        return this.removeAt(index);
    };
    this.toString=function(){
        let current=head;
        let string='';
        while(current){
            string+=current.element+(current.next?'n':'');
            current=current.next;
        }
        return string;
    };
    this.isEmpty=function(){
        return length===0;
    };  
    this.size=function(){
        return length;
    };
    this.getHead=function(){
        return head;
    };
}

实现双向链表

function DoublyLinkedList(){
    let Node=function(element){
        this.element=element;
        this.next=null;
        this.prev=null;
    };
    let length=0;
    let head=null;
    let tail=null;
    this.insert=function(position,element){
        //检查越界
        if(position>=0&&position<=length){
            let node=new Node(element);
            let current=head;
            let previous;
            let index=0;
            if(position===0){
                if(!head){
                    head=node;
                    tail=node;
                }else{
                    node.next=current;
                    current.prev=node;
                    head=node;
                }
            }else if(position===length){
                current=tail;
                current.next=node;
                node.prev=current;
                tail=node;
            }else{
                while(index<position){
                    previous=current;
                    current=current.next;
                    index++;
                }
                node.next=current;
                current.prev=node;
                previous.next=node;
                node.prev=previous;
            }
            length++;
            return true;
        }else{
            return false;
        }
    };
    this.removeAt=function(position){
        if(position>=0&&position<length){
            let current=head;
            let previous;
            let index=0;
            if(position===0){
                head=current.next;
                if(length===1){
                    tail=null;
                }else{
                    head.prev=null;
                }
            }else if(position===length-1){
                current=tail;
                tail=current.prev;
                tail.next=null;
            }else{
                while(index<position){
                    previous=current;
                    current=current.next;
                    index++;
                }
                previous.next=current.next;
                current.next.prev=previous;
            }
            length--;
            return current.element;
        }else{
            return null;
        }
    }
}

集合

集合是由一组无序且唯一(即不能重复)的项组成的,ECMAScript 6原生支持Set类

集合实现

function Set(){
    let items={};
    this.has=function(value){
        return value in items;
    };
    this.add=function(value){
        if(!this.has(value)){
            items[value]=value;
            return true;
        }
        return false;
    };
    this.remove=function(value){
        if(this.has(value)){
            delete items[value];
            return true;
        }
        return false;
    };
    this.clear=function(){
        items={};
    };
    this.size=function(){
        return Object.keys(items).length;
    };
    this.values=function(){
        let values=[];
        for(let i=0,keys=Object.keys(items);i<keys.length;i++){
            values.push(items[keys[i]]);
        }
        return values;
    }
}
//使用Set类
let set=new Set();

实现集合操作

  1. 并集
function Set(){
    //其他实现代码

    //Set类的union方法
    this.union=function(otherSet){
        let unionSet=new Set();
        let values=this.values();
        for(let i=0;i<values.length;i++){
            unionSet.add(values[i]);
        }
        values=otherSet.values();
        for(let i=0;i<values.length;i++){
            unionSet.add(values[i]);
        }
        return unionSet;
    }
}
  1. 交集
function Set(){
    //其他实现代码

    this.intersection=function(otherSet){
        let intersectionSet=new Set();
        let values=this.values();
        for(let i=0;i<values.length;i++){
            if(otherSet.has(values[i])){
                intersectionSet.add(values[i]);
            }
        }
        return intersectionSet;
    }
}
  1. 差集
function Set(){
    //其他实现代码

    this.difference=function(otherSet){
        let differenceSet=new Set();
        let values=this.values();
        for(i=0;i<values.length;i++){
            if(otherSet.has(values[i])){
                differenceSet.add(values[i]);
            }
        }
        return differenceSet;
    }
}
  1. 子集
function Set(){
    //其他实现代码

    this.subset=function(otherSet){
        if(this.size()>otherSet.size()){
            return false;
        }else{
            let values=this.values();
            for(let i=0;i<values.length;i++){
                if(!otherSet.has(values[i])){
                    return false;
                }
            }
            return true;
        }
    }
}

字典和散列表

字典和集合很相似,集合以[值,值]的形式存储元素,字
典则是以[键,值]的形式来存储元素。字典也称作映射,字典的键是唯一的

字典实现

function Dictionary(){
    let items={};
    this.has=function(key){
        return key in items;
    };
    this.set=function(key,value){
        items[key]=value;
    };
    this.delete=function(key){
        if(this.has(key)){
            delete items[key];
            return true;
        }
        return false;
    };
    this.get=function(key){
        return this.has(key)?items[key]:undefined;
    };
    this.values=function(){
        let values=[];
        for(let key in items){
            values.push(items[key]);
        }
        return values;
    };
    this.keys=function(){
        return Object.keys(items);
    };
    this.getItems=function(){
        return items;
    };
}
//使用Dictionary 类
let dictionary=new Dictionary();

散列映射和字典一样键是唯一的,散列映射的键对应的散列值代表实际值在散列表中的地址
散列函数:键值经过散列函数得到散列值

散列表实现

function HashTable(){
    let table=[];
    //散列函数
    let loseloseHashCode=function(key){
        let hash=0;
        for(let i=0;i<key.length;i++){
            hash+=key.charCodeAt(i);
        }
        return hash%37;
    };
    this.put=function(key,value){
        let position=loseloseHashCode(key);
        console.log(position+' - '+key);
        table[position]=value;
    };
    this.get=function(key){
        return table[loseloseHashCode(key)];
    };
    this.remove=function(key){
        table[loseloseHashCode(key)]=undefined;
    };
}
//使用 HashTable 类
let hash=new HashTable();

散列集合和集合一样值是唯一的,散列的值对应的散列值代表实际值在散列表中的地址
散列函数:实际值经过散列函数得到散列值


和散列映射一样是非顺序数据结构,对于存储需要快速查找的数据非常有用

tree.jpg

二叉树和二叉搜索树
二叉树中的节点最多只能有两个子节点:一个是左侧子节点,另一个是右侧子节点。
二叉搜索树(BST)是二叉树的一种,但是它只允许你在左侧节点存储(比父节点)小的值,
在右侧节点存储(比父节点)大(或者等于)的值

实现二叉搜索树

function BinarySearchTree(){
    let Node=function(key){
        this.key=key;
        this.left=null;
        this.right=null;
    };
    let root=null;
    //插入节点方法
    this.insert=function(key){
        let newNode=new Node(key);
        if(root===null){
            root=newNode;
        }else{
            insertNode(root.newNode);
        }
    };
    //插入节点辅助函数
    let insertNode=function(node,newNode){
        if(newNode.key<node.key){
            if(node.left===null){
                node.left=newNode;
            }else{
                insertNode(node.left,newNode);
            }
        }else{
            if(node.right===null){
                node.right=newNode;
            }else{
                insertNode(node.right,newNode);
            }
        }
    };
    //树的遍历-中序遍历
    this.inOrderTraverse=function(callback){
        inOrderTraverseNode(root,callback);
    };
    let inOrderTraverseNode=function(node,callback){
        if(node!==null){
            inOrderTraverseNode(node.left,callback);
            callback(node.key);
            inOrderTraverseNode(node.right,callback);
        }
    };
    //树的遍历-先序遍历
    this.preOrderTraverse=function(callback){
        preOrderTraverseNode(root,callback);
    };
    let preOrderTraverseNode=function(node,callback){
        if(node!==null){
            callback(node.key);
            preOrderTraverseNode(node.left,callback);
            preOrderTraverseNode(node.right,callback);
        }
    };
    //树的遍历-后序遍历
    this.postOrderTraverse=function(callback){
        postOrderTraverseNode(root,callback);
    };
    let postOrderTraverseNode=function(node,callback){
        if(node!==null){
            postOrderTraverseNode(node.left,callback);
            postOrderTraverseNode(node.right,callback);
            callback(node.key);
        }
    };
    //搜索树中的值
    //搜索最小值
    this.min=function(){
        return minNode(root);
    };
    let minNode=function(node){
        if(node){
            while(node&&node.left!==null){
                node=node.left;
            }
            return node.key;
        }
        return null;
    };
    //搜索最大值
    this.max=function(){
        return maxNode(root);
    };
    let maxNode=function(node){
        if(node){
            while(node&&node.right!==null){
                node=node.right;
            }
            return node.key;
        }
        return null;
    };
    //搜索特定值
    this.search=function(key){
        return searchNode(root,key);
    };
    let searchNode=function(node,key){
        if(node===null){
            return false;
        }
        if(key<node.key){
            return searchNode(node.left,key);
        }else if(key>node.key){
            return searchNode(node.right,key);
        }else{
            return true;
        }
    };
    //移除节点
    this.remove=function(key){
        root=removeNode(root,key);
    };
    let removeNode=function(node,key){
        if(node==null){
            return null;
        }
        if(key<node.key){
            node.left=removeNode(node.left,key);
            return node;
        }else if(key>node.key){
            node.right=removeNode(node.right,key);
            return node;
        }else{
            if(node.left===null&&node.right===null){
                node=null;
                return node;
            }
            if(node.left===null){
                node=node.right;
                return node;
            }else if(node.right===null){
                node=node.right;
                return node;
            }
            let aux=findMinNode(node.right);
            node.key=aux.key;
            node.right=removeNode(node.right,aux.key);
            return node;
        }
    };
    let findMinNode=function(node){
        while(node&&node.left!==null){
            node=node.left;
        }
        return node;
    };
    
}
let tree=new BinarySearchTree();
function printNode(value){
    console.log(value);
}
//调用中序遍历
tree.inOrderTraverse(printNode);
//调用先序遍历
tree.preOrderTraverse(printNode);
//调用后序遍历
tree.postOrderTraverse(printNode);
上一篇下一篇

猜你喜欢

热点阅读