内容:栈、行列、链表、鸠合、字典、散列表、树
栈
- 经由过程类封装完成栈构造,不直接继续数组的原生要领的原因是,数组具有某些其他数据构造的要领,为了只让栈暴露栈的要领,还得编写将非栈的要领关闭的代码,多了冗余代码,且不是面向对象编程的合理表现。
//栈,要领包含入栈操纵、出栈操纵、返回栈顶元素、推断栈是不是为空、清空栈、栈的长度
//这里栈实例对象的要领都可看做闭包函数,items可看做类的私有变量,只要类实例的要领来访问,而items也是栈内容的存储实体。
function Stack(){
var items = [];
this.push = function(ele){
items.push(ele);
};
this.pop = function(){
items.pop();
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
this.peek = function(){
return items[items.length-1];
}
this.isEmpty = function(){
return items.length > 0 ? false : true;
}
}
var stack = new Stack();
console.log(stack);
stack.push(2);
console.log(stack.size());
console.log(stack.isEmpty());
行列
- 基本完成
//行列,要领包含入队操纵、出队操纵、返回队首元素、推断行列是不是为空、清空行列、行列的长度
function Queue(){
var items = [];
this.inqueue = function(ele){
items.push(ele);
};
this.outqueue = function(){
items.shift();
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
this.front = function(){
return items[0];
}
this.isEmpty = function(){
return items.length > 0 ? false : true;
}
}
- 优先级行列
考虑到行列中每一个元素具有优先级,所以行列中的元素采纳对象来完成,具有两个属性:元素的值和元素的优先级。
//优先级行列
function PriorityQueue(){
var items = [];
function QueueElement(element,priority){
this.element = element;
this.priority = priority;
}
this.inqueue = function(element,priority){
var queueElement = new QueueElement(element,priority);
if(this.isEmpty()){
items.push(queueElement);
}else{
for(var i=0;i<items.length;i++){
if(items[i].priority > priority){
items.splice(i,0,queueElement);
break;
}else if(i === (items.length-1)){
items.push(queueElement);
break; // 这里一定要break,不然会轮回插进去,致使堆溢出
}
}
}
};
this.outqueue = function(){
items.shift();
};
this.size = function(){
return items.length;
};
this.clear = function(){
items = [];
};
this.front = function(){
return items[0].element;
}
this.isEmpty = function(){
return items.length > 0 ? false : true;
}
this.get = function(){
return items;
}
}
- 轮回行列/伐鼓传花游戏
能够换个角度想:一排凳子,所有人轮回去坐,伐鼓以后,坐在第一个凳子(队头)上的人镌汰,即下面代码参考的思绪。
//轮回行列
//伐鼓传花游戏,以牢固轮回次数来模仿每轮伐鼓的牢固时长,该游戏会一轮一轮迭代,每轮镌汰一人,直到只剩末了一人即为胜者
function hotPotato(namelist,num){
var queue = new Queue();
for(var i=0;i<namelist.length;i++){
queue.inqueue(namelist[i]);
}
while(queue.size() > 1){
for(i=0;i<num;i++){
var nowElement = queue.front();
queue.outqueue();
queue.inqueue(nowElement);
}
var deletElement = queue.front();
queue.outqueue();
console.log(deletElement+"在伐鼓传花游戏中被镌汰");
}
return queue.front();
}
var list = ["hahah","askdjvzxv","uuuuu","aaaaa","bbbbbb","ccccc"];
var winner = hotPotato(list,5);
console.log("胜利者是:"+winner);
链表
- 由于链表中每一个元素都有指向下一个元素的指针,所以链表中每一个元素应用对象来完成,对象具有两个属性:元素的值和指向下一个元素的指针;在指定位置插进去或删除元素,都须要注重与前一个和后一个元素之间指针的关联;
//链表,元素在内存中非一连安排,要领包含链表尾部到场/删除元素,链表指定位置到场/删除元素,找出元素在链表中的索引,链表是不是为空,链表的长度
function LinkedList(){
var head = null;//链表第一个元素的援用
var length = 0;//链表的长度,不然追求size很贫苦
var end = null;//链表末了一个元素的援用,轻易插进去/删除元素
function Node(element){
this.element = element;
this.next = null;
}
//从链表尾部到场node元素
this.appendList = function(element){
var node = new Node(element);
if(head === null){
head = node;
}else{
end.next = node;
}
end = node;
length++;
};
//从链表指定位置到场node元素,0示意在链表头插进去该元素
this.appendListAt = function(position,element){
var node = new Node(element);
if(position > 0){
var frontNode = this.findNodeAt(position);
var afterNode = frontNode.next;
frontNode.next = node;
node.next = afterNode;
length++;
}else if(position === 0){
node.next = head;
head = node;
length++;
}
};
//从链表尾部删除node元素
this.removeList = function(){
if(head !== null){
var findNode = this.findNodeAt(length-1);
end = findNode;
findNode.next = null;
length--;
}
};
//从链表指定位置删除node元素
this.removeListAt = function(position){
if(position > 1){ //永久检测用户输入
var frontNode = this.findNodeAt(position-1);
var afterNode = frontNode.next.next;
frontNode.next = afterNode;
length--;
}else if(position = 1){
head = head.next;
length--;
}
};
//链表的大小
this.size = function(){
return length;
};
this.isEmpty = function(){
return head === null ? true : false;
}
this.toString = function(){
var iterNode = head;
var outString = [];
outString.push(head.element);
for(var i=1;i<length;i++){
iterNode = iterNode.next;
outString.push(iterNode.element);
}
return outString;
}
//封装一个可共用的函数,找出指定位置的node元素
this.findNodeAt = function(position){
var iterNode = head;
while(position > 1){
iterNode = iterNode.next;
position--;
}
return iterNode;
}
}
鸠合
- 采纳对象来完成鸠合,对象的属性寄存元素值,由于对象中的属性无序,能够很好地模仿鸠合的特征
//鸠合,鸠合类的要领包含增加/删除元素,是不是有某值,消灭鸠合,鸠合大小
function Set(){
var items = {};
this.has = function(value){
return items.hasOwnProperty(value);
}
//向鸠合中增加元素
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 false;
}
this.size = function(){
return Object.keys(items).length;
}
this.clear = function(){
items = {};
}
this.values = function(){
return Object.keys(items); //返回对象自身中可罗列属性
}
//鸠合的交集,并集,差集,子集要领
//并集
this.union = function(setB){
var setAvalues = this.values();
var setUnion = new Set();
for(var i=0;i<setAvalues.length;i++){
setUnion.add(setAvalues[i]);
}
var setBvalues = setB.values();
for(var j=0;j<setBvalues.length;j++){
setUnion.add(setBvalues[j]);
}
return setUnion;
}
//交集
this.intersection = function(setB){
var setAvalues = this.values();
var intersectionSet = new Set();
var setBvalues = setB.values();
for(var i=0;i<setAvalues.length;i++){
if(setB.has(setAvalues[i])){
intersectionSet.add(setAvalues[i]);
}
}
return intersectionSet;
}
//差集
this.difference = function(setB){
var setAvalues = this.values();
var differenceSet = new Set();
var setBvalues = setB.values();
for(var i=0;i<setAvalues.length;i++){
if(!setB.has(setAvalues[i])){
differenceSet.add(setAvalues[i]);
}
}
return differenceSet;
}
//子集
this.isSubsetOf = function(setB){
var setAvalues = this.values();
var setBvalues = setB.values();
for(var i=0;i<setAvalues.length;i++){
if(!setB.has(setAvalues[i])){
return false;
}
}
return true;
}
}
字典
- 有鸠合的完成相似
//采纳对象来完成字典,以key-value的情势存储,由于对象中的属性无序,字典的要领包含经由过程key来增加/删除元素,是不是有某值,消灭字典,字典大小
function Dictionary(){
var items = {};
this.has = function(key){
return items.hasOwnProperty(key);
}
//向字典中增加元素
this.set = function(key,value){
if(!this.has(key)){
items[key] = value;
return true;
}
return false;
}
//删除字典中的元素
this.remove = 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.size = function(){
return Object.keys(items).length;
}
this.clear = function(){
items = {};
}
this.keys = function(){
return Object.keys(items); //返回对象自身中可罗列属性
}
this.values = function(){
var res = [];
for(key in items){
if(items.hasOwnProperty(key)){
res.push(items[key]);
}
}
return res;
}
//猎取全部字典对象
this.getItems = function(){
return items;
}
}
二叉搜刮树
- 二叉搜刮树中每一个节点都有三个属性。值,左援用,右援用。
- 注重在完成时,拿到节点对象的援用,并不能对节点自身举行删除,最好删除节点的要领是将上一个节点的援用指向置为null,并将节点对象的援用置为null(开释内存,关照渣滓接纳)
//二叉搜刮树
function BinarySearchTree(){
var rootNode = null;
function TreeNode(key){
this.key = key;
this.left = null;
this.right = null;
}
//向树中插进去新节点
this.insert = function(key){
var treeNode = new TreeNode(key);
if(rootNode === null){
rootNode = treeNode;
}else{
insertNode(rootNode,treeNode);
}
}
function insertNode(node,treeNode){
if(treeNode.key < node.key){
if(node.left === null){
node.left = treeNode;
}else{
insertNode(node.left,treeNode);
}
}else if(treeNode.key > node.key){
if(node.right === null){
node.right = treeNode;
}else{
insertNode(node.right,treeNode);
}
}
}
//先序遍历
this.preOrderTraverse = function(){
if(rootNode === null){
console.log("没有节点");
}else{
pretraverse(rootNode);
}
}
function pretraverse(node){
if(node !== null){
pretraverse(node.left);
console.log(node.key);
pretraverse(node.right);
}
}
//中序遍历
this.inOrderTraverse = function(){
if(rootNode === null){
console.log("没有节点");
}else{
intraverse(rootNode);
}
}
function intraverse(node){
if(node !== null){
console.log(node.key);
intraverse(node.left);
intraverse(node.right);
}
}
//后序遍历
this.posOrderTraverse = function(){
if(rootNode === null){
console.log("没有节点");
}else{
postraverse(rootNode);
}
}
function postraverse(node){
if(node !== null){
postraverse(node.left);
postraverse(node.right);
console.log(node.key);
}
}
//移除树中的节点
this.remove = function(key){
rootNode = removeNode(rootNode,key);
}
function removeNode(node,key){
if(node === null){
return null;
}
if(key < node.key){
node.left = removeNode(node.left,key);
return node; //与下面三个return node的功用都是保证removeNode的返回值为删除节点后树的根节点
}else if(key > node.key){
node.right = removeNode(node.right,key);
return node;
}else{
if(node !== null){ //考虑到被删除节点的三种状况
if((node.left === null) && (node.right === null)){
node = null;//这里只是为了渣滓接纳node,下面作用都相似
return node;//这里才是删除的功用,这里的返回是为了让node.left = removeNode(node.left,key);中node.left=null;
}else if((node.left === null) && (node.right !== null)){
var temp = node.right;
node = null;
return temp;
}else if((node.left !== null) && (node.right === null)){
var temp = node.left;
node = null;
return temp;
}else if((node.left !== null) && (node.right !== null)){
var findNode = findMin(node.right);
node.key = findNode.key;
node.right = removeNode(node.right,findNode.key);
return node;
}
}
}
}
function findMin(node){
while(node.left !== null){
node = node.left;
}
return node;
}
//查找某个节点
this.search = function(key){
var node = rootNode;
while((node !== null) && (node.key !== key)){
if(key < node.key){
node = node.left;
}else if(key > node.key){
node = node.right;
}
}
return (node !== null) ? true : false;
}
//猎取树中最小值
this.min = function(){
var node = rootNode;
while(node.left !== null){
node = node.left;
}
return node.key;
}
//猎取树中最大值
this.max = function(){
var node = rootNode;
while(node.right !== null){
node = node.right;
}
return node.key;
}
this.getRootNodeKey = function(){
return rootNode.key;
}
}