什么是数据结构
- 数据结构就是在计算机中,存储和组织数据的方式
- 如何以高效的方式组织和储存数据?
什么是算法(Algorithm)
- 不同的算法,执行效率是不一样的
- 一个有限指令集,每条指令的描述不依赖于语言
- 接受一些输入
- 产生输出
- 一定会在有限步骤之后终止
为了更加方便的插入和搜索数据,需要合理的组织数据,并且通过更加高效的算法插入和查询数据。
数组结构
普通语言的数组封装:
- 常见语言的数组不能存放不同的数据类型,因此常见语言在封装时通常存放在数组中的是Object类型
- 常见语言的数组容量不会自动改变
- 常见语言的数组进行中间插入和删除操作时性能比较低
栈结构
- 栈(stack),它是一种运算受限的线性表,后进先出(LIFO);
- LIFO(last in first out)表示就是后进入的元素, 第一个弹出栈空间. 类似于自动餐托盘, 最后放上的托盘, 往往先把拿出去使用;
- 其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底;
- 向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;
- 从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素;
push()
可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
pop()
从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。
peek()
返回栈顶的元素,不对栈做任何修改(这个方法不会移除栈顶的元素,仅仅返回
它)。
isEmpty()
如果栈里没有任何元素就返回true,否则返回false。
clear()
移除栈里的所有元素。
size()
返回栈里的元素个数。这个方法和数组的length属性很类似。
栈的实例:函数调用栈
递归:不断调用自己,将自己压入栈中,可能导致栈溢出
栈结构的实现
实现栈结构的俩种比较常见的方式
- 基于数组实现
- 基于链表实现
<script>
//method: 和某一个对象实例有联系
//function
//封装栈类
function Stack() {
//栈中的属性
this.items = [];
//栈的相关操作
//1.将元素压入栈
Stack.prototype.push = function(element) {
this.items.push(element);
}
//2.从栈中取出元素
Stack.prototype.pop = function() {
return this.items.pop();
}
//3.查看一下栈顶元素
Stack.prototype.peek = function() {
return this.items[this.items.length - 1];
}
//4.判断栈是否为kong
Stack.prototype.isEmpty = function() {
return this.items.length == 0;
}
//5.获取栈中元素的个数
Stack.prototype.size = function() {
return this.items.length;
}
//6.toString方法
Stack.prototype.toString = function() {
var resultString = '';
for( var i = 0; i < this.items.length; i++) {
resultString += this.items[i];
}
return resultString;
}
}
//栈的使用
var s = new Stack();
s.push(20);
s.push(10);
s.push(100);
s.push(120);
document.write(s + '<br/>');
s.pop();
s.pop();
document.write(s + '<br/>');
document.write(s.peek() + '<br/>');
document.write(s.isEmpty() + '<br/>');
document.write(s.size() + '<br/>');
document.write(resultString + '<br/>');
</script>
十进制转二进制:
//函数十进制转二进制
function dec2bin(decNumber) {
//1.定义栈对象
var stack = new Stack();
//2.循环操作
while(decNumber > 0) {
//2.1获取余数,并放入栈中
stack.push(decNumber % 2);
//2.2获取整除后的结果,作为下一次运行的数字
decNumber = Math.floor(decNumber / 2);
}
//3.从栈中取出0和1
var binaryString = '';
while(!stack.isEmpty()) {
binaryString += stack.pop();
}
return binaryString;
}
//测试十进制转二进制
alert(dec2bin(100)); //1100100
alert(dec2bin(10)); //1010
alert(dec2bin(1000)); //1111101000
队列结构 Queue
- 一种受限的线性表,先进先出
- 受限之处在于它只允许在表的前端进行删除操作
- 而在表的后端进行插入操作
需要排队的场景都是会用到队列的地方,如打印队列、线程队列…
enqueue(element) :
向队列尾部添加一个(或多个)新的项。
dequeue() :
移除队列的第一(即排在队列最前面的)项,并返回被移除的元素。
front() :
返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。
isEmpty() :
如果队列中不包含任何元素,返回true,否则返回false。
size() :
返回队列包含的元素个数,与数组的length属性类似。
优先级队列
优先级队列在插入元素时会考虑该数据的优先级
线程处理的任务重要性不同,可以通过优先级的大小,来决定该线程在队列中被处理的次序。
实现优先级队列:
- 封装元素和优先级放在一起(可以封装一个新的构造函数)
- 添加元素时,将新插入元素的优先级和队列中以及存在的元素优先级进行比较,以获得自己正确的位置。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>优先级队列</title>
</head>
<body>
<script>
function PriorityQueue(argument) {
//在 PriorityQueue类中重新创建一个类,可以理解为内部类
function QueueElement(element, priority) {
this.element = element;
this.priority = priority;
}
//封装属性
this.items = [];
//实现插入方法
PriorityQueue.prototype.enqueue = function(element, priority) {
//1.创建QueueElement对象
var queueElement = new QueueElement(element, priority);
//2.判断队列是否为空
if(this.items.length == 0) {
//2.1若数组为空,则直接插入数据
this.items.push(queueElement);
} else {
//2.2循环遍历数组中每一个数据的优先级和新插入的数据的优先级进行比较,比较后插入
var added = false;
for(var i = 0;i < this.items.length; i++) {
if (queueElement.priority < this.items[i].priority) {
this.items.splice(i, 0, queueElement);
//一旦插入则跳出循环
added = true;
break;
}
}
//2.3若是该数据比现有数组中的所有数据的优先级都大,则放在最后
if (!added) {
this.items.push(queueElement);
}
}
//2.从队列中删除前端元素
PriorityQueue.prototype.dequeue = function () {
return this.items.shift();
}
//3.查看前端的元素
PriorityQueue.prototype.front = function () {
return this.items[0];
}
//4.查看队列是否为空
PriorityQueue.prototype.isEmpty = function () {
return this.items.length == 0;
}
//5.查看队列中元素的个数
PriorityQueue.prototype.size = function () {
return this.items.length;
}
//6.toString方法
PriorityQueue.prototype.toString = function () {
var resultString = '';
for(var i=0; i < this.items.length; i++) {
resultString += this.items[i].element + '-' + this.items[i].priority + ' ';
}
return resultString;
}
}
}
//测试代码
var pq = new PriorityQueue();
//enqueue方法
pq.enqueue('abc',145);
pq.enqueue('bdd',58);
pq.enqueue('ajs',187);
pq.enqueue('oep',12);
alert(pq.toString());
//oep-12 bdd-58 abc-145 ajs-187
console.log(pq.items);
</script>
</body>
</html>