JavaScript数据结构算法(字典,散列表,图的数据结构)

字典:如下

//映射字典能够数用的方法;
/*
set(key,value):向字典中添加新的元素
remove(key):通过使用键值来从字典中移除键值对应的数据值;
has(key):如果某个键值存在于这个字典中,返回true,反之返回false;
get(key):通过键值来查找特定的数值并返回
clear();将这个字典中的所有元素全部删除;
size();返回字典所半酣的元素的数量,与数组的length属性类似。
keys():将字典所包含的所有键名以数组的形式返回。
values();将字典所包含的所有的数值 以数组的形式返回。
 */
function Dictionary() {
    var item = {};//注意此处是一个Object对象,不是数组中存储元素
    this.has = function (key) {
        return key in item;//判断key是不是item对象中的一个属性。
    }
    this.set = function (key, value) {
        item[key] = value;//将value设为item对象的key属性的值;添加新的值或更新一个已有的值。
    }
    this.remove = function (key) {
        if (this.has(key)) {
            delete item[key];//使用js中的delete操作符来从item中移除key属性;
            return true;
        } else {
            return false;
        }
    }
    this.get = function (key) {
        return this.has(key) ? item[key] : undefined;
    }
    this.values = function () {
        var values = [];
        for (var k in item) {
            if (this.has(k)) {
                values.push(item[k])//以数组的形式返回字典中所有的values实例的值。
            }
        }
        return values;
    }
    this.keys = function () {
        var keys = [];
        for (var k in item) {
            if (this.has(k)) {
                keys.push(k)//以数组的形式返回字典中所有的values实例的值。
            }
        }
        return keys;
    }
    this.getItems=function(){
        return item;
    }

}
var dictionary=new Dictionary();
dictionary.set('Gandalf', '[email protected]'); 
dictionary.set('John', '[email protected]'); 
dictionary.set('Tyrion', '[email protected]');
console.log(dictionary.has('Gandalf'));
console.log(dictionary.keys());
console.log(dictionary.values()); 
console.log(dictionary.get('Tyrion'));
dictionary.remove('John');
console.log(dictionary.keys()); 
console.log(dictionary.values()); 
console.log(dictionary.getItems());

运行结果: 

JavaScript数据结构算法(字典,散列表,图的数据结构)_第1张图片

散列表:

/*
HashTable类,也叫HashMap类,是dictionary类的一种散列表的实现方式;
散列算法的作用是尽可能再数据结构中找到一个值,你已经这道了要在数据结构中获得一个值
用get()方法,需要遍历整个数据结构来找到它,如果使用散列的函数,就知道值的具体的位置,因此能够快速检索到该值。散
因此可以快速的检索到该值。散列函数的作用是给定一个键值,然后返回值在表中的地址。
*/
/*
 方法如下:
 put(key,value):向散列表增加一个新的项(也能更新散列表)。
 remove(key):根据键值从散列表中移除值。
 get(key):返回根据键值检索到的特定的值。
 在实现这三个方法之前,要实现的第一个方法是散列函数,它是HashTable类中的一个私有
方法:
 */
var loseloseHashCode = function (key) {
    var hash = 0;
    for (var i = 0; i < key.length; i++) {//给定一个key参数,我们就能根据组成key的每个字符的ASCII码值的和得到一个数字
        hash += key.charCodeAt(i);
    }
    return hash % 37;//为了得到比较小的数值,我们会使用hash值和一个任意数做除法的余数(mod)。
}
function HashTable() {
    var table = [];
    this.put = function (key, value) {
        var position = loseloseHashCode(key);
        if (table[position] == undefined) {  //将验证要加入新元素的位置是否已经被占据
            table[position] = new LinkedList();
            //如果这个位置是第一次被加入元素,我们会在这个位置上初始化一个LinkedList类的实例
        }
        table[position].append(new ValuePair(key, value));
        //实现的append方法向LinkedList实例中添加一个ValuePair实例(键和值)
    };
    this.get = function (key) {
        var position = loseloseHashCode(key);
        //是确定在特定的位置上是否有元素存在
        if (table[position] !== undefined) {
            //遍历链表来寻找键/值
            var current = table[position].getHead();
            while (current.next) {
                //遍历这个链表来寻找我们需要的元素。在遍历之前先要获取链表表头的引用

                if (current.element.key === key) {
                    return current.element.value;
                }
                current = current.next;
            }
            //检查元素在链表第一个或最后一个节点的情况
            if (current.element.key === key) {
                return current.element.value;
            }
        }
        return undefined;
    };
    this.remove = function (key) {
        table[loseloseHashCode(key)] = undefined;//返回undefined即不存在
    };

    //分离链接
    var ValuePair = function (key, value) {
        this.key = key;
        this.value = value;
        this.toString = function () {
            return '[' + this.key + '-' + this.value + ']';
        }
    }
}
var hashTable = new HashTable();
hashTable.put('peng', '');
console.log(hashTable.get('peng'));//19-peng
//如果存储的键的位置相同,那么会出现后来的覆盖前面的。如何避免
//处理冲突的方法:分离链接、先行探查、双散列法。
//分离链接:包括为散列表的没一个位置创建一个链表,并且将元素存储在里面。解决冲突的最简单的方法,
//但是它在HashTable实例之外需要额外的存储空间。
//增加一个新的辅助类来表示要加入的LinkeList实例的元素。
//在HashTable类内部定义

/*
线性探查,想向表中某个位置加入一个新元素的时候,如果索引
为index的位置已经被占据了,就尝试index+1的位置。 如果
index+1的位置也被占据了,就尝试index+2的位置,以此类推。

*/
//(1) put方法 4
//让我们继续实现需要重写的三个方法。第一个是put方法:
this.put = function (key, value) {
    var position = loseloseHashCode(key);
    if (table[position] == undefined) {
        table[position] = new ValuePair(key, value);
    } else {
        var index = ++position;
        while (table[index] != undefined) {
            index++; // {6} 
        }
        table[index] = new ValuePair(key, value);
    }
};
//(2) get方法
//现在插入了所有的元素,让我们实现get方法来获取它们的值吧: 3 
this.get = function (key) {
    var position = loseloseHashCode(key);
    if (table[position].key === key) {
        return table[position].value;
    } else {
        var index = ++position;
        while (table[index] === undefined || table[index].key !== key) {
            index++;
        }
        if (table[index].key === key) {
            return table[index].value;
        }
    }
    return undefined;
};
//(3) remove方法
//remove方法和get方法基本相同;
table[index] = undefined; 
// 要移除一个元素,只需要给其赋值为undefined,来表示这个位置不再被占据并且可以在必
// 要时接受一个新元素。

//一个实现起来比lose lose更好的散列函数,没有冲突!虽然这并不是最好的散列函数,但是这是被社区推荐的散列函数之一


var djb2HashCode = function (key) { 
    var hash = 5381;  
    for (var i = 0; i < key.length; i++) { 
    hash = hash * 33 + key.charCodeAt(i);  
    } 
    return hash % 1013;  
   };
   /*
它包括初始化一个hash变量并赋值为一个质数( ——大多数实现都使用5381),然后
迭代参数key ,将hash与33相乘(用来当作一个魔力数),并和当前迭代到的字符的ASCII
码值相加 
   */

实现图: 

function Dictionary() {
    var item = {};//注意此处是一个Object对象,不是数组中存储元素
    this.has = function (key) {
        return key in item;//判断key是不是item对象中的一个属性。
    }
    this.set = function (key, value) {
        item[key] = value;//将value设为item对象的key属性的值;添加新的值或更新一个已有的值。
    }
    this.remove = function (key) {
        if (this.has(key)) {
            delete item[key];//使用js中的delete操作符来从item中移除key属性;
            return true;
        } else {
            return false;
        }
    }
    this.get = function (key) {
        return this.has(key) ? item[key] : undefined;
    }
    this.values = function () {
        var values = [];
        for (var k in item) {
            if (this.has(k)) {
                values.push(item[k])//以数组的形式返回字典中所有的values实例的值。
            }
        }
        return values;
    }
    this.keys = function () {
        var keys = [];
        for (var k in item) {
            if (this.has(k)) {
                keys.push(k)//以数组的形式返回字典中所有的values实例的值。
            }
        }
        return keys;
    }
    this.getItems=function(){
        return item;
    }

}
function Graph() {
    var vertices = [];
    var adjList = new Dictionary();
    this.addVertex = function (v) {//添加新的顶点
        vertices.push(v);//添加顶点
        adjList.set(v, []);
    }
    this.addEdge = function (v, w) {
        adjList.get(v).push(w);//v--->w的边
        adjList.get(w).push(v);//w--->v的边,
        //如果是无向图,则有一个语句就行了。此处表述的是有向图;

    }
    this.toString = function () {
        var s = '';
        for (var i = 0; i < vertices.length; i++) {
            s += vertices[i] + ' -> ';
            var neighbors = adjList.get(vertices[i]);
            for (var j = 0; j < neighbors.length; j++) {
                s += neighbors[j] + ' ';
            } 9
            s += '\n';
        }
        return s;
    };
}
var graph = new Graph();
var myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
for (var i = 0; i < myVertices.length; i++) { //添加顶点
    graph.addVertex(myVertices[i]);
}
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');
console.log(graph.toString())

运行结果:

JavaScript数据结构算法(字典,散列表,图的数据结构)_第2张图片

你可能感兴趣的:(JavaScript数据结构,JavaScript数据结构)