一、数据结构
概念:
- 数据结构(data structure)是计算机中存储、组织数据的方式
常见的数据结构:
- 栈、队列、链表、集合、字典、树...
注:
常见的数据结构较多, 每一种都有其对应的应用场景, 不同数据结构的不同操作性能是不同的
数据结构和语言无关, 基本常见的编程语言都有直接或者间接的使用上述常见的数据结构
算法:
-
一个有限指令集, 每条指令的描述不依赖于语言
-
接受一些输入(有些情况下不需要输入)
-
产生输出
-
一定在有限步骤之后终止
-
解决问题的办法/步骤逻辑
注:数据结构的实现, 离不开算法
二、栈
栈结构:
- 是一种运算受限的线性表 其限制是仅允许在表的一端进行插入和删除运算
- 受限的这一端被称为栈顶,相对地,把另一端称为栈底
- 后进先出 last in first out (LIFO) :后进入的元素先弹出栈空间,先进入的元素后弹出栈空间
-
向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素
-
从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素
程序实现栈结构:
栈的常见操作:
push(element)
: 添加一个新元素到栈顶位置.
pop()
:移除栈顶的元素,同时返回被移除的元素
peek()
:返回栈顶的元素,不对栈做任何修改(该方法不会移除栈顶的元素,仅仅返回它)
isEmpty()
:如果栈里没有任何元素就返回true
,否则返回false
clear()
:移除栈里的所有元素
size()
:返回栈里的元素个数。这个方法和数组的length
属性很类似
1.ES5封装栈结构
(1)将方法绑在函数对象上
function Stack() {
//开辟空间,保存栈元素
this.item = []
//1.向栈顶添加元素 数组的最后添加元素
this.push = function (el) {
this.item.push(el)
}
//2.移除栈顶元素并返回栈顶元素 数组的最后一个元素
this.pop = function () {
return this.item.pop()
}
//3.返回栈顶元素 数组的最后一个元素
this.peek = function () {
return this.item.length - 1
}
//4.判空 栈为空true 数组的length长度来判断栈是否为空
this.isEmpty = function () {
return this.item.length == 0
}
//5.清空栈
this.clear = function () {
this.item = []
}
//6.栈元素的个数
this.size = function () {
return this.item.length
}
}
let stack = new Stack()
stack.push(2)
console.log(stack.item)
(2)将方法绑在原型上
function Stack() {
//开辟空间,保存栈元素
this.item = []
//1.向栈顶添加元素 数组的最后添加元素
Stack.prototype.push = function (el) {
this.item.push(el)
}
//2.移除栈顶元素并返回栈顶元素 数组的最后一个元素
Stack.prototype.pop = function () {
return this.item.pop()
}
//3.返回栈顶元素 数组的最后一个元素
Stack.prototype.peek = function () {
return this.item.length - 1
}
//4.判空 栈为空true 数组的length长度来判断栈是否为空
Stack.prototype.isEmpty = function () {
return this.item.length == 0
}
//5.清空栈
Stack.prototype.clear = function () {
this.item = []
}
//6.栈元素的个数
Stack.prototype.size = function () {
return this.item.length
}
}
let stack1 = new Stack()
stack.push(3)
console.log(stack.item)
2.ES6封装栈结构
class Stack {
constructor() {
//开辟空间,保存栈元素
this.item = []
}
//1.向栈顶添加元素 数组的最后添加元素
push(el) {
this.item.push(el)
}
//2.移除栈顶元素并返回栈顶元素 数组的最后一个元素
pop() {
return this.item.pop()
}
//3.返回栈顶元素 数组的最后一个元素
peek() {
return this.item.length - 1
}
//4.判空 栈为空true 数组的length长度来判断栈是否为空
isEmpty() {
return this.item.length == 0
}
//5.清空栈
clear() {
this.item = []
}
//6.栈元素的个数
size() {
return this.item.length
}
}
let stack1 = new Stack()
stack.push(3)
console.log(stack.item)
实例(进制转换):
- 引入封装的栈结构
- 十进制转任意进制:余数压栈 (终止条件:栈为空)
function Desbasebin(num,base) {
//1.创建一个空栈
let stack = new Stack()
let arr=["A","B","C","D","E","F"]
while (num > 0) {
//余数
let yushu = num % base
//余数压栈
if(yushu>9){
//16进制
stack.push(arr[yushu-10])
}
else{
stack.push(yushu)
}
num = Math.floor(num / base)
}
// console.log(stack.item)
let str = ''
//栈不为空时 依次出栈
while (!stack.isEmpty()) {
str +=stack.pop()
}
return str
}
console.log(Desbasebin(100,2)) //转2进制
console.log(Desbasebin(100,8)) //转8进制
console.log(Desbasebin(100,16)) //转16进制
结果:
三、队列
队列结构:
- 是一种运算受限的线性表 先进先出(FIFO First In First Out)
-
受限之处在于它只允许在表的前端(front)进行删除操作,在表的后端(rear)进行插入操作
程序实现队列结构:
队列常见的操作
enqueue(element)
:向队列尾部添加一个(或多个)新的项
dequeue()
:移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
front()
:返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack
类的peek
方法非常类似)
isEmpty()
:如果队列中不包含任何元素,返回true
,否则返回false
size()
:返回队列包含的元素个数,与数组的length
属性类似
ES6封装队列结构:
class Queue {
constructor() {
this.item = []
}
//1.入队
enqueue(el) {
this.item.push(el)
}
//2.出队
delqueue() {
return this.item.shift()
}
//3.返回队首元素
front() {
return this.item[0]
}
//4.判空
isEmpty() {
return this.item.length == 0
}
//5.返回元素的个数
size() {
return this.item.length
}
}
实例(击鼓传花):
- 引入封装的队列结构
- 让栈中的每第三个元素出栈 前两个元素先出栈再入栈 直到最后只剩一个元素就是获胜者
function game(arr) {
// 创建队列 依次入队
let queue = new Queue()
// for (let i = 0; i < arr.length; i++) {
// queue.enqueue(arr[i])
// }
arr.forEach(el=> {
queue.enqueue(el)
});
console.log(queue.item)
// 数数
let count = 1
while (queue.size() > 1) { //队列中只有一个元素事啊停止
if (count < 3) {
let node = queue.delqueue() //先出队
queue.enqueue(node) //再入队
count++
} else {
//直接出队
queue.delqueue()
count = 1
}
}
return{
winner:queue.front(),
position:arr.indexOf(queue.front())
}
}
var arr = ["哈哈哈", "嘻嘻嘻", "呵呵呵", "哟哟哟", "嗷嗷嗷", "哦哦哦"]
console.log(game(arr))
结果:
四、优先级队列
- 在插入一个元素的时候会考虑该数据的优先级(和其他数据优先级进行比较)
- 比较完成后, 可以得出这个元素正确的队列中的位置. 其他处理方式, 和队列的处理方式一样
程序实现优先级队列:
class Node {
constructor(data, priority) {
this.data = data
this.priority = priority
}
}
class PriorityQueue {
constructor() {
this.item = []
}
enqueue(ele, priority) {
// let newobj={data:ele,pro:priority}
//创建新节点
let newnode = new Node(data, priority)
if (this.item.length == 0) {
//空队列 直接添加元素到队列中
this.item.push(newnode)
} else {
//非空队列 依次比较优先级
let isAdd = false //元素是否被添加到队列中
for (let i = 0; i < this.item.length; i++) {
console.log(this.item[i])
if (newnode.priority < this.item[i].priority) {
//新节点的优先级小于队列元素的优先级
this.item.splice(i, 0, newnode) //将新节点插入到队列中
isAdd = true
break
}
}
//循环遍历结束都没有比新节点小的元素,直接添加元素到队列的最后
if (!isAdd) {
this.item.push(newnode)
}
}
}
}
let pq=new PriorityQueue()
pq.enqueue("haha",21)
pq.enqueue("xixi",13)
pq.enqueue("yoyo",16)
pq.enqueue("heihei",4)
console.log(pq.item)