数据结构和算法
什么是数据结构
- 在计算机中,存储和组织数据的方式
- 例如:图书馆图书摆放、快递摆放
什么是算法
- 解决问题的方法和步骤
- 通常用来更加高效的获取数据和处理数据
数组
- 数组是线性结构
- 可以在数组的任意位置插入和删除元素
- 在数组的开头或中间位置,插入和删除元素效率低,需要位移其他元素
- 数组的查找和修改元素效率非常高
栈 Stack,后进先出(LIFO)
- 栈(stack)是一种受限的线性结构,仅允许在表的一端进行插入和删除运算。
- 可操作的一端:栈顶; 不可操作的一端:栈底
- LIFO:Last In First Out , 最后一个进,第一个出
- 相当于有底的存储桶:例如,叠盘子、储物箱,就是先放的就在底部,后放的在上面,后进先出
- 添加:进栈
- 删除:出栈
- 特点:后进先出
- 程序中的栈的应用
- 函数调用栈:A函数 调用 B函数, B函数 又调用 C函数
- 递归:不断调用自己,会不断压栈,很容易出现栈溢出
- 栈面试题
- 答案:C
- 栈的封装
- 栈中常见的操作
- 栈的封装
<script>
// 栈的封装
function Stack() {
// 栈中的属性
this.items = [];
// 栈的相关操作
// 1. 进栈
Stack.prototype.push = function (item) {
this.items.push(item);
}
// 2. 从栈中取出元素
Stack.prototype.pop = function () {
return this.items.pop();
}
// 3. 查看栈顶元素
Stack.prototype.peek = function () {
return this.items[this.items.length - 1];
}
// 4. 判断栈是否为空
Stack.prototype.isEmpty = function () {
return this.items.length === 0;
}
// 5. 获取栈中的个数
Stack.prototype.size = function () {
return this.items.length;
}
// 6. toString 方法
Stack.prototype.toString = function () {
// 主要是返回形式
return this.items.toString();
}
}
var s = new Stack();
s.push(20);
s.push(30);
s.push(40);
console.log('栈顶元素 peek: ', s.peek())
console.log('取出栈顶元素 pop: ', s.pop())
console.log('判断栈是否为空 isEmpty: ', s.isEmpty())
console.log('栈的长度 size: ', s.size())
console.log('返回栈元素的拼接字符串 toString: ', s.toString())
</script>
- 十进制转二进制
- toString() 方法:①转为字符串; ②已十进制为基地,转化为对应的参数进制
- parseInt() 方法:①parseInt(a) 将变量转化为整型,从左往右检查,直到非数字字符为止;②直接使用方法,有两个参数,parseInt(a, b),表示 a 已 b 进制为基底,转化为 十进制
- 利用封装好的 Stack 栈,实现十进制转二进制操作
<script>
// 栈的应用:十进制转二进制
function decTobin (decNumber) {
// 新建栈
var stack = new Stack();
while (decNumber > 0) {
stack.push(decNumber % 2)
decNumber = Math.floor(decNumber / 2)
}
var binStr = '';
while (!stack.isEmpty()) {
binStr += stack.pop()
}
console.log(binStr)
}
</script>
队列(Queue)
- 队列:受限的线性结构,先进先出(FIFO, First Int First Out)
- 只允许在表的前端(first)进行删除操作,表的后端(rear)进行插入操作
- 例如:排队(不允许插队)
- 队列的应用
- 打印队列:打印机会按先进入的文档先打印,后进入的文档后打印
- 线程队列:当线程过多时,排队等候执行
- 队列的封装
- 队列常见操作
- 封装队列
<script>
// 利用数组封装队列
function Queue() {
// 属性
this.items = [];
// 1. 元素加入队列
Queue.prototype.enqueue = function (item) {
this.items.push(item);
}
// 2. 从队列中删除前端元素
Queue.prototype.dequeue = function () {
return this.items.shift();
}
// 3. 查看前端元素
Queue.prototype.front = function () {
return this.items[0];
}
// 4. 查看队列是否为空
Queue.prototype.isEmpty = function () {
return this.items.length === 0;
}
// 5. 查看队列中元素的个数
Queue.prototype.size = function () {
return this.items.length;
}
// 6. toString方法
Queue.prototype.toString = function () {
// 返回怎样类型的字符串自己定义
return this.items.toString();
}
}
// 使用队列
var queue = new Queue();
// 入队
queue.enqueue('a');
queue.enqueue('b');
queue.enqueue('c');
queue.enqueue('d');
console.log(queue.toString())
console.log("查看队列中的个数", queue.size())
console.log("出队", queue.dequeue())
console.log("出队后", queue.toString())
</script>
- 面试题:击鼓传花
- 规则
- 实现
<script>
// 击鼓传花:利用队列解决问题
function passGame(nameList, num) {
// 1. 创建一个队列结构
var que = new Queue();
// 2. 将所有人加入到队列中
for(var i = 0; i < nameList.length; i++) {
que.enqueue(nameList[i]);
}
while (que.size() > 1) {
// 3. 开始数数,num之前的重新加入队列末尾
for(var i = 0; i < num - 1; i++){
que.enqueue(que.dequeue())
}
// 数到num的那个人直接删除
que.dequeue()
}
// 4. 获取剩下的那个人
console.log(que.front())
}
</script>
优先级队列
-
优先级队列,每个元素包含数据和优先级,添加数据会先根据优先级进行比较,然后再插入正确的位置
-
优先级队列应用
- 优先级队列的实现,主要是添加元素的操作,需要根据队列中每个元素的优先级进行比较,然后决定插入的位置
<script>
// 封装优先级队列
function PriorityQueue () {
// 在 PriorityQueue重新创建一个类:内部类
function QueueElement(element, priority) {
this.element = element;
this.priority = priority;
}
// 属性
this.items = [];
// 1. 插入方法
PriorityQueue.prototype.enqueue = function (element, priority) {
// 1. 创建 QueueElement 对象
var queueElement = new QueueElement(element, priority);
// 2. 判断队列是否为空
if (this.items.length === 0) {
this.items.push(queueElement);
} else {
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;
}
}
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 () {
// 返回怎样类型的字符串自己定义
// return this.items.toString();
var str = "";
this.items.forEach(item => {
str += `${item.element} `
})
console.log(str);
return str.trim();
}
}
var pq = new PriorityQueue();
pq.enqueue(12, 3);
pq.enqueue(13, 2);
pq.enqueue(14, 1);
console.log(pq.size())
console.log(pq.toString())
</script>