字典
字典是一种以键-值对形式存储数据的数据结构,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]
}
}
}
散列
散列是一种常用的数据存储技术,散列后的数据可以快速地插入或取用。散列使用的数据结构叫做散列表。
整个散列过程其实就是两步。
- 在存储时,通过散列函数计算记录的散列地址,并按此散列地址存储该记录。
- 当查找记录时,我们通过同样的散列函数计算记录的散列地址,按此散列地址访问该记录。
实现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
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。