字典

字典是一种以键-值对模式存储数据的数据结构,JavaScript的Object类就是以字典的模式设计的。上面用代码实现字典类以及相干操作方法

Dictionary类

datastore为数据集

class Dictionary{  datastore=[]  constructor(){  }}

add()增加键值对

add(key, value) {    this.datastore[key]=value  }

get()失去键的值

get(key) {    return this.datastore[key]  }

remove()移除元素

remove(key) {    delete this.datastore[key]  }

showAll()打印全副信息

showAll() {    for(let key in this.datastore){      console.log(`key=>${this.datastore[key]}`)    }  }

clear()清空操作

clear() {    for(let key in this.datastore){     delete this.datastore[key]    }  }

残缺代码

class Dictionary {    datastore = []    constructor() {    }    add(key, value) {        this.datastore[key] = value    }    find(key) {        return this.datastore[key]    }    remove(key) {        delete this.datastore[key]    }    showAll() {        for (let key in this.datastore) {            console.log(`key=>${this.datastore[key]}`)        }    }    count() {        let num = 0        for (let key in this.datastore) {            num++        }        return num    }    clear() {        for (let key in this.datastore) {            delete this.datastore[key]        }    }}

散列

散列是一种罕用的数据存储技术,散列后的数据能够疾速地插入或取用。散列应用的数据结构叫做散列表。

整个散列过程其实就是两步。

  1. 在存储时,通过散列函数计算记录的散列地址,并按此散列地址存储该记录。
  2. 当查找记录时,咱们通过同样的散列函数计算记录的散列地址,按此散列地址拜访该记录。

实现HashTable类

class HashTable{  table=new Array(137)  constructor(){  }}

hash()散列函数应用霍纳算法计算键值

hash(string){    const H = 37;    var total = 0;    for (var i = 0; i < string.length; ++i) {        total += H * total + string.charCodeAt(i);    }    total = total % this.table.length;    if (total < 0) {         total += this.table.length-1;    }    return parseInt(total);  }

put()用来将数据存入散列表

put(key,data){    let pos = this.hash(key)    this.table[pos]=data  }

showDistro()示散列表中的数据

showDistro(){    for(let index=0,length=this.table.length;index<length;index++){      if(this.table[index]){        console.log(`index:${this.table[index]}`)      }    }  }

get()获取对应的键值

get(key) {        return this.table[hash(key)]    }

残缺代码

class HashTable {    table = new Array(137)    constructor() {    }    hash(string) {        const H = 37;        var total = 0;        for (var i = 0; i < string.length; ++i) {            total += H * total + string.charCodeAt(i);        }        total = total % this.table.length;        if (total < 0) {            total += this.table.length - 1;        }        return parseInt(total);    }    showDistro() {        for (let index = 0, length = this.table.length; index < length; index++) {            if (this.table[index]) {                console.log(`index:${this.table[index]}`)            }        }    }    put(key, data) {        let pos = this.hash(key)        this.table[pos] = data    }    get(key) {        return this.table[hash(key)]    }}

碰撞解决

当散列函数对于多个输出产生同样的输入时,就产生了碰撞。解决两碰撞解决办法次要有两种:链地址法和凋谢定址法。

1.链地址法

链地址法是指实现散列表的底层数组中,每个数组元素又是一个新的数据结构,比方另一个数组,这样就能存储多个键了。应用这种技术,即便两个键散列后的值雷同,仍然被保留在同样的地位,只不过它们在第二个数组中的地位不一样罢了

结构散列表

class HashTableChains{  table=new Array(137).fill([])  constructor(){  }}

要从新定义put()和get()办法。put()办法将键值散列,散列后的值对应数组中的一个地位,先尝试将数据放到该地位上的数组中的第一个单元格,如果该单元格里曾经有数据了,put()办法会搜寻下一个地位,直到找到能搁置数据的单元格,并把数据存储进去

  put(key,data){    let pos = this.hash(key)    let index=0    if(this.table[pos][index]==undefined){      this.table[pos][index]=data    }else{      while(this.table[pos][index]!=undefined){        index++      }      this.table[pos][index]=key      this.table[pos][index+1]=data    }    }  get(key){    let hash = this.hash(key)    let index=0    if(this.table[hash][index]==key){      return this.table[hash][index+1]    }else{      while(this.table[hash][index]!=key&&this.table[hash][index]!=undefined){        index+=2      }      if(this.table[hash][index]!=undefined){        return this.table[hash][index+1]      }     }    return undefined  }

残缺代码

class HashTableChains{  table=new Array(137).fill([])  constructor(){  }  hash(string){    const H = 37;    var total = 0;     for (var i = 0; i < string.length; ++i) {        total += H * total + string.charCodeAt(i);     }    total = total % this.table.length;     if (total < 0) {         total += this.table.length-1;    }    return parseInt(total);  }  showDistro(){    for(let index=0,length=this.table.length;index<length;index++){      if(this.table[index][0] != undefined){        console.log(`index:${this.table[index]}`)      }    }  }  put(key,data){    let pos = this.hash(key)    let index=0    if(this.table[pos][index]==undefined){      this.table[pos][index]=data    }else{      while(this.table[pos][index]!=undefined){        index++      }      this.table[pos][index]=key      this.table[pos][index+1]=data    }  }  get(key){    let hash = this.hash(key)    let index=0    if(this.table[hash][index]==key){      return this.table[hash][index+1]    }else{      while(this.table[hash][index]!=key&&this.table[hash][index]!=undefined){        index+=2      }      if(this.table[hash][index]!=undefined){        return this.table[hash][index+1]      }      }    return undefined  } }
2. 凋谢定址法

凋谢定址法隶属于一种更一般化的散列技术:凋谢寻址散列。当产生碰撞时,凋谢定址法查散列表中的下一个地位是否为空。如果为空,就将数据存入该地位;如果不为空,则持续查看下一个地位,直到找到一个空的地位为止。
线性探测法工作,须要重写put()和get()办法。

结构散列表

新增加一个属性values用来存散列表每个键对应的值

class HashTableLinear{  table=new Array(137)  values=new Array(137)  constructor(){  }}

重写put()和get()办法

put(key,data){    let pos = this.hash(key)    if(this.table[pos]==undefined){      this.table[pos]=key      this.values[pos]=data    }else{      while(this.table[pos]!=undefined){        pos++      }      this.table[pos]=key      this.values[pos]=data    }      }  get(key){    let pos = this.hash(key)    if(this.table[pos]==key){      return this.values[pos]=data    }else{      while(this.table[pos]!=key&&this.table[pos]!=undefined){        pos++      }      if(this.table[pos]!=undefined){        return this.values[pos]=data      }         }    return undefined  }

残缺代码

class HashTableLinear{  table=new Array(137)  values=new Array(137)  constructor(){  }  hash(string){    const H = 37;    var total = 0;     for (var i = 0; i < string.length; ++i) {        total += H * total + string.charCodeAt(i);     }    total = total % this.table.length;     if (total < 0) {         total += this.table.length-1;    }    return parseInt(total);  }  showDistro(){    for(let index=0,length=this.table.length;index<length;index++){      if(this.table[index]){        console.log(`index:${this.table[index]}=>${this.values[index]}`)      }    }  }  put(key,data){    let pos = this.hash(key)    if(this.table[pos]==undefined){      this.table[pos]=key      this.values[pos]=data    }else{      while(this.table[pos]!=undefined){        pos++      }      this.table[pos]=key      this.values[pos]=data    }      }  get(key){    let pos = this.hash(key)    if(this.table[pos]==key){      return this.values[pos]=data    }else{      while(this.table[pos]!=key&&this.table[pos]!=undefined){        pos++      }      if(this.table[pos]!=undefined){        return this.values[pos]=data      }         }    return undefined  }}

汇合

汇合是一种蕴含不同元素的数据结构。汇合中的元素称为成员。汇合的两个最重要个性是:首先,汇合中的成员是无序的;其次,汇合中不容许雷同成员存在。当你想要创立一个数据结构,用来保留一些举世无双的元素时,汇合就变得十分有用。

Set类的实现

class SetList{  dataStore=[]  constructor(){  }}

add()增加元素

add(ele) {        if (this.dataStore.indexOf(ele) == -1) {            this.dataStore.push(ele)            return true        } else {            return false        }    }

remove()移除元素

remove(ele) {        let position = this.dataStore.indexOf(ele)        if (position != -1) {            this.dataStore.splice(position, 1)            return true        } else {            return false        }    }

size()返回数据量

  size() {        return this.dataStore.length    }

show() 展现数据集

show(){    return this.dataStore  }

contains(),该办法查看一个成员是否属于该汇合

contains(ele) {        return this.dataStore.indexOf(ele) != -1    }

union() 办法执行并集操作

  union(set) {        let unionSet = new SetList()        this.dataStore.forEach(item => {            unionSet.add(item)        })        set.dataStore.forEach(item => {            unionSet.add(item)        })        return unionSet    }

intersect() 办法求两个汇合的交加

intersect() {        let intersectSet = new SetList()        this.dataStore.forEach(item => {            if (set.contains(item)) {                intersectSet.add(item)            }        })        return intersectSet    }

subset() 判断是否是指标汇合的子集

subset(set) {        if (set.size() < this.size()) {            return false        }        this.dataStore.forEach(item => {            if (!set.contains(item)) {                return false;            }        })        return true    }

difference(),该办法返回一个新汇合,该汇合蕴含的是那些属于第一个汇合但不属于第二个汇合的成员。

difference(set) {        let differencetSet = new SetList()        this.dataStore.forEach(item => {            if (!set.contains(item)) {                differencetSet.add(item)            }        })        return differencetSet    }

实现代码

class SetList {    dataStore = []    constructor() {    }    add(ele) {        if (this.dataStore.indexOf(ele) == -1) {            this.dataStore.push(ele)            return true        } else {            return false        }    }    remove(ele) {        let position = this.dataStore.indexOf(ele)        if (position != -1) {            this.dataStore.splice(position, 1)            return true        } else {            return false        }    }    size() {        return this.dataStore.length    }    contains(ele) {        return this.dataStore.indexOf(ele) != -1    }    union(set) {        let unionSet = new SetList()        this.dataStore.forEach(item => {            unionSet.add(item)        })        set.dataStore.forEach(item => {            unionSet.add(item)        })        return unionSet    }    intersect() {        let intersectSet = new SetList()        this.dataStore.forEach(item => {            if (set.contains(item)) {                intersectSet.add(item)            }        })        return intersectSet    }    subset(set) {        if (set.size() < this.size()) {            return false        }        this.dataStore.forEach(item => {            if (!set.contains(item)) {                return false;            }        })        return true    }    difference(set) {        let differencetSet = new SetList()        this.dataStore.forEach(item => {            if (!set.contains(item)) {                differencetSet.add(item)            }        })        return differencetSet    }    show() {        return this.dataStore    }}