哈希表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
1. 数组进行插入删除操作,效率低
2. 查找
2.1 如果基于索引进行查找效率高
2.2 如何基于内容去查找效率低
3. 修改
3.1 基于索引 修改效率高
3.2 基于内容 效率低
哈希表基于数组实现
插入 删除 查找 操作非常高
哈希表的速度比树还要快
缺点: 数据是没有顺序的,key值不能重复
哈希表在哈希化的时候,产生的下标值发生冲突,解决办法有
两种: 1、链地址法(拉链法) 2. 开放地址法
</body>
<script>
function hashFunc(str, size) {
let hashCode = 0;
for (let i = 0; i < str.length; i ++ ) {
hashCode = 37 * hashCode + str.charCodeAt(i)
}
let index = hashCode % size
return index
}
function HashTable () {
this.storage = []
this.count = 0
this.limit = 7
HashTable.prototype.hashFunc =function (str, size) {
let hashCode = 0;
for (let i = 0; i < str.length; i ++ ) {
hashCode = 37 * hashCode + str.charCodeAt(i)
}
let index = hashCode % size
return index
}
HashTable.prototype.put = function (key, value) {
let index = this.hashFunc(key, this.limit)
let bucket = this.storage[index]
if (bucket === null) {
bucket = []
this.storage[index] = bucket
}
for (let i = 0; i < bucket.length; i++) {
let tuple = bucket[i]
if (tuple[0] == key ) {
tuple[1] = value
return
}
}
bucket.push([key, value])
this.count += 1
if (this.count > this.limit * 0.75) {
let sizeNum = this.limit * 2
let newSize = this.getpreim(sizeNum)
this.resize(newSize)
}
}
HashTable.prototype.get = function (key) {
let index = this.hashFunc(key, this.limit)
let bucket = this.storage[index]
if (bucket === null) {
return null
}
for (let i = 0; i < bucket.length; i++) {
let tuple = bucket[i]
if (tuple[0] === key) {
return tuple[1]
}
}
return null
}
HashTable.prototype.remove = function (key) {
let index = this.hashFunc(key, this.limit)
let bucket = this.storage[index]
if (bucket === null) {
return null
}
for (let i = 0; i < bucket.length; i++) {
let tuple = bucket[i]
if (tuple[0] === key) {
bucket.splice(i,1)
this.count -= 1
return tuple[1]
if (this.limit > 7 && this.count < this.limit * 0.25){
let sizeNum = Math.floor(this.limit / 2)
let newSize = this.getpreim(sizeNum)
this.resize(newSize)
}
}
}
return null
}
HashTable.prototype.isEmpty = function () {
return this.count == 0
}
HashTable.prototype.size = function () {
return this.count
}
HashTable.prototype.resize = function (newLimit) {
let oldSrorage = this.storage
this.storage = []
this.count = 0
this.limit = newLimit
for (let i = 0; i< oldSrorage.length; i++) {
let bucket = oldSrorage[i]
if (bucket == null) {
continue
}
for (let j = 0; j < bucket.length; j++) {
let tuple = bucket[j]
this.put(tuple[0], tuple[1])
}
}
}
HashTable.prototype.isPre = function (num) {
let temp = parseInt(Math.sqrt(num))
for (let i = 2; i <= temp; i++) {
if (num % i == 0) {
return false
}
}
return true
}
HashTable.prototype.getpreim = function (num) {
while(!this.isPre(num)) {
num ++
}
return num
}
}
function isPrime(num) {
for( let i = 2; i< num; i++) {
if (num % i == 0) {
return false
}
}
return true
}
function isPre(num) {
let temp = parseInt(Math.sqrt(num))
for (let i = 2; i <= temp; i++) {
if (num % i == 0) {
return false
}
}
return true
}
alert(hashFunc('abc', 7))
</script>
</html>
集合
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
function Set() {
this.items = {}
Set.prototype.has = function (value) {
return this.items.hasOwnProperty(value)
}
Set.prototype.add = function (value) {
if (this.has(value)) {
return false
}
this.items[value] = value
return true
}
Set.prototype.remove = function (value) {
if (!this.has(value)) {
return false
}
delete this.items[value]
return true
}
Set.prototype.clear = function () {
this.items = {}
}
Set.prototype.size = function (value) {
return Object.keys(this.items).length
}
Set.prototype.values = function (value) {
return Object.keys(this.items)
}
Set.prototype.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
}
Set.prototype.intersection = function (otherSet) {
let intersectionSet = new Set()
let values = this.values()
for (let i = 0; i< values.length; i ++) {
let item = values[i]
if (otherSet.has(item)) {
intersectionSet.add(item)
}
}
return intersectionSet
}
Set.prototype.difference = function (otherSet) {
let differenceSet = new Set()
let values = this.values()
for (let i = 0; i < values.length; i++) {
let item = values[i]
if (!otherSet.has(item)) {
differenceSet.add(item)
}
}
return differenceSet
}
Set.prototype.subSet = function (otherSet) {
let values = this.values()
for (let i = 0; i< values.length; i ++) {
let item = values[i]
if (!otherSet.has(item)) {
return false
}
}
return true
}
}
</script>
</html>
链表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
function LinkedList() {
function Node (data) {
this.data = data;
this.next = null;
}
this.head = null;
this.length = 0;
LinkedList.prototype.append = function (data) {
let newNode = new Node(data)
if (this.length === 0) {
this.head = newNode
} else {
let current = this.head
while (current.next) {
current = current.next
}
current.next = newNode
}
this.length += 1;
}
LinkedList.prototype.toString = function() {
let current = this.head
let listString = ""
while (current) {
listString += current.data + ""
current = current.next
}
return listString
}
LinkedList.prototype.insert = function (position, data) {
if (position < 0 || position > this.length) return false;
let newNode = new Node(data)
if (position === 0) {
newNode.next = this.head
this.head = newNode
} else {
let index = 0
let current = this.head
let previous = null
while (index ++ < position) {
previous = current
current = current.head
}
newNode.next = current
previous.next = newNode
}
this.length += 1
return true
}
LinkedList.prototype.get = function (position) {
if (position < 0 || position >= this.length) return false;
let current = this.head
let index = 0
while (index++ < position) {
current = current.next
}
return current.data
}
LinkedList.prototype.indexOf = function (data) {
let current = this.head
let index = 0
while (current) {
if (current.data === data) {
return index
}
current = current.next
index += 1
}
return -1
}
LinkedList.prototype.update = function (position, newDate) {
if (position < 0 || position >= this.length) return false;
let current = this.head
let index = 0
while (index++ < position) {
current = current.next
}
current.data = newDate
return true
}
LinkedList.prototype.removeAt = function (position) {
if (postion < 0 || position >= this.length) return null;
let current = this.head
if (position === 0) {
this.head = this.head.next
} else {
let index = 0;
let previous = null
while (index ++ < position) {
previous = current
current = current.next
}
previous.next = current.next
}
this.length -= 1
return current.data
}
LinkedList.prototype.remove = function (data) {
let postion = this.indexOf(data)
return this.removeAt(position)
}
}
let list = new LinkedList()
list.append('abc')
list.append('ccc')
console.log(list, '---list')
alert(list)
</script>
</html>
双向链表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
function DoubleLinkedList() {
function Node(data) {
this.data = data
this.prev = null
this.next = null
}
this.head = null
this.tail = null
this.length = 0
// append方法
DoubleLinkedList.prototype.append = function (data) {
let newNode = new Node(data)
if (this.length === 0) {
this.head = newNode
this.tail = newNode
} else {
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
}
this.length += 1
}
DoubleLinkedList.prototype.toString = function () {
return this.backwardString()
}
DoubleLinkedList.prototype.forwardString = function () {
let current = this.tail
let resultString = ""
while (current) {
resultString += current.data + " "
current = current.prev
}
return resultString
}
DoubleLinkedList.prototype.backwardString = function () {
let current = this.head
let resultString = ""
while (current) {
resultString += current.data + ""
current = current.next
}
return resultString
}
DoubleLinkedList.prototype.insert = function (position, data) {
if (position < 0 || position > this.length) return false
let newNode = new Node(data)
// 判断原来的列表是否为 空
if (this.length === 0) {
this.head = newNode
this.tail = newNode
} else {
// 给最前面添加
if (position === 0) {
// 原来的第一个节点。prev = newNode
// newNode.next = 原来的第一个节点
this.head.prev = newNode
newNode.next = this.head
this.head = newNode
} else if (position === this.length) { // 给最后面添加
newNode.prev = this.tail
this.tail.next = newNode
this.tail = newNode
} else { // 插入到中间
let current = this.head
let index = 0
while (index++ < position) {
current = current.next
}
newNode.next = current
newNode.prev = current.prev
current.prev.next = newNode
current.prev = newNode
}
}
this.length += 1
}
// get(position)
DoubleLinkedList.prototype.get = function (position) {
if (position < 0 || position >= this.length) return null
let index = 0
let current = this.head
while (index++ < position) {
current = current.next
}
return current.data
// 优化 TODO
// this.length /2 > position 从前往后遍历
// this.length / 2 < position 从后往前
}
DoubleLinkedList.prototype.indexOf = function (data) {
let index = 0
let current = this.head
while (current) {
if (current.data === data) {
return index
}
current = current.next
index += 1
}
return -1
}
DoubleLinkedList.prototype.update = function (position, newdata) {
if (position < 0 || position >= this.length) return false
let index = 0
let current = this.head
while (index++ < position) {
current = current.next
}
current.data = newdata
return true
}
DoubleLinkedList.prototype.removeAt = function (position) {
if (position < 0 || position >= this.length) return null
let current = this.head
if (this.length === 1) {
this.tail = null
this.head = null
} else {
// 判断是否删除的是第一个节点
if (position == 0) {
this.head.next.prev = null
this.head = this.head.next
} else if (position === this.length -1) {
current = this.tail
this.tail.prev.next = null
this.tail = this.tail.prev
} else {
let index = 0
while (index++ < position) {
current = current.next
}
current.prev.next = current.next
current.next.prev = current.prev
}
}
this.length -= 1
return current.data
}
DoubleLinkedList.prototype.remove = function (data) {
let index = this.indexOf(data)
return this.removeAt(index)
}
}
let DoubleList = new DoubleLinkedList()
</script>
</html>
队列(优先级队列)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
function PriorityQueue() {
function QueElement(element, priority) {
this.element = element
this.priority = priority
}
this.items = []
PriorityQueue.prototype.enqueue = function (element, priority) {
let queElement = new QueElement(element, priority)
if (this.items.lenght === 0) {
this.items.push(queElement)
} else {
let added = false
for (let i = 0; i< this.items.length; i ++) {
if (queElement.priority < this.items[i].priority) {
this.items.splice(i, 0, queElement)
added = true
break
}
}
if (!added) {
this.items.push(queElement)
}
}
}
}
let pq = new PriorityQueue()
function Stack() {
this.items = [];
Stack.prototype.push = function(ele) {
this.items.push(ele)
}
Stack.prototype.pop = function() {
this.items.pop()
}
Stack.prototype.peek = function() {
return this.items[items.lenght - 1]
}
Stack.prototype.isEmpty = function () {
return this.items.lenght === 0
}
Stack.prototype.size = function () {
return this.items.lenght
}
Stack.prototype.toString = function () {
return this.items.toString()
}
}
let stack = new Stack()
</script>
</html>
树
class Tree {
constructor () {
this.root = null;
this.Node = function Node (key) {
this.key = key
this.left = null
this.right = null
};
}
insertNode (node, newNode) {
if (newNode.key < node.key) {
if (node.left === null) {
node.left = newNode
} else {
this.insertNode(node.left, newNode)
}
} else {
if (node.right === null) {
node.right = newNode
} else {
this.insertNode(node.right, newNode)
}
}
}
insert (key) {
let newNode = new this.Node(key)
if (this.root === null) {
this.root = newNode
} else {
this.insertNode(this.root, newNode)
}
}
preOrderTreeNode (node, handler) {
if (node !== null) {
handler(node.key)
this.preOrderTreeNode(node.left, handler)
this.preOrderTreeNode(node.right, handler)
}
}
preOrderTree (handler) {
this.preOrderTreeNode(this.root, handler)
}
midOrderTree(handler) {
this.midOrderTreeNode(this.root, handler)
}
midOrderTreeNode(node, handler) {
if (node !== null) {
this.midOrderTreeNode(node.left, handler)
handler(node.key)
this.midOrderTreeNode(node.right, handler)
}
}
min() {
let node = this.root;
let key = null;
while(node !== null) {
key = node.key
node = node.left
}
return key
}
max () {
let node = this.root
let key = null
while(node !== null) {
key = node.key
node = node.right
}
return key
}
search (key) {
let node = this.root
while (node !== null) {
if (node.key > key) {
node = node.left
} else if (key > node.key) {
node = node.right
} else if (key === node.key){
return true
}
}
return false
}
remove (key) {
let current = this.root
let parent = null
let isLeftChild = true
while (current.key !== key) {
parent = current
if (key < parent.key) {
isLeftChild = true
current = current.left
} else {
isLeftChild = false
current = current.right
}
if (current === null) return false
}
if (current.right === null && current.left === null) {
if (current === this.root) {
this.root = null
} else if (isLeftChild) {
parent.left = null
} else {
parent.right = null
}
}
else if (current.right === null && isLeftChild) {
if (current === this.root) {
this.root = current.left
} else {
parent.left = current.left
}
}
else if (current.right === null && !isLeftChild) {
if (current === this.root) {
this.root = current.left
} else {
parent.right = current.left
}
}
else if (current.left === null && isLeftChild) {
if (current === this.root) {
this.root = current.right
} else {
parent.left = current.right
}
}
else if (current.left === null && !isLeftChild) {
if (current === this.root) {
this.root = current.right
} else {
parent.right = current.right
}
}
else {
let successor = this.getend(current)
if (current === this.root) {
this.root = successor
} else if (isLeftChild) {
parent.left = successor
} else {
parent.right = successor
}
successor.left = current.left
}
}
getend(delNode) {
let successor = delNode
let current = delNode.right
let successorParent = delNode
while (current !== null) {
successorParent = successor
successor = current
current = current.left
}
if ( successor !== delNode.right) {
successorParent.left = successor.right
successor.right = delNode.right
}
return successor
}
}
let bst = new Tree()
bst.insert(11)
bst.insert(7)
bst.insert(15)
bst.insert(5)
bst.insert(3)
bst.insert(9)
bst.insert(8)
bst.insert(10)
bst.insert(13)
bst.insert(12)
bst.insert(14)
bst.insert(20)
bst.insert(18)
bst.insert(25)
console.log(bst)
let resultString = ""
bst.preOrderTree((key) => {
resultString += key + " "
})
console.log(resultString.split(" "), '先序遍历')
let resultString1 = ""
bst.midOrderTree((key) => {
resultString1 += key + " "
})
console.log(resultString1.split(" "), '中序遍历')
console.log(bst.min(), bst.max())
字典
function Dictionay() {
this.items = {}
Dictionay.prototype.set = function (key, value) {
this.items[key] = value
}
Dictionay.prototype.has = function (key) {
return this.items.hasOwnProperty(key)
}
Dictionay.prototype.remove = function (key) {
if (!this.has(key)) return false
delete this.items[key]
return true
}
Dictionay.prototype.get = function (key) {
return this.has(key) ? this.items[key] : undefined
}
Dictionay.prototype.keys = function () {
return Object.keys(this.items)
}
Dictionay.prototype.size = function () {
return this.keys().length
}
Dictionay.prototype.clear = function () {
this.items = {}
}
}
图
function Graph() {
this.vertexes = []
this.edges = new Dictionay()
Graph.prototype.addVertex = function (v) {
this.vertexes.push(v)
this.edges.set(v, [])
}
Graph.prototype.addEdges = function (v1, v2) {
this.edges.get(v1).push(v2)
this.edges.get(v2).push(v1)
}
Graph.prototype.toString = function () {
let resultString = ""
for (let i = 0; i< this.vertexes.length; i ++) {
resultString += this.vertexes[i] + '--->'
let vEdges = this.edges.get(this.vertexes[i])
for (let j = 0; j< vEdges.length; j ++) {
resultString += vEdges[j] + ' '
}
resultString += '\n'
}
return resultString
}
Graph.prototype.initColor = function () {
let colors = []
for (let i = 0; i< this.vertexes.length; i++) {
colors[this.vertexes[i]] = 'white'
}
return colors
}
Graph.prototype.bfs = function (initV, handler) {
let colors = this.initColor()
let queue = new Queue()
queue.enqueue(initV)
while (!queue.isEmpty()) {
let v = queue.dequeue()
let vList = this.edges.get(v)
colors[v] = 'gray'
for (let i = 0; i< vList.length; i ++) {
let e = vList[i]
if (colors[e] === 'white') {
colors[e] = 'gray'
queue.enqueue(e)
}
}
handler(v)
colors[v] = 'black'
}
}
Graph.prototype.dfs = function (initV, handler) {
let colors =this.initColor()
this.dfsVisit(initV, colors, handler)
}
Graph.prototype.dfsVisit =function (v, colors, handler) {
colors[v] = 'gray'
handler(v)
let vList = this.edges.get(v)
for (let i = 0; i< vList.length; i++) {
let e = vList[i]
if (colors[e] === 'white') {
this.dfsVisit(e, colors, handler)
}
}
colors[v] = 'black'
}
}