数据结构
数据结构并没有官方的定义,在民间有各种定义;
1、数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系;
2、数据结构是计算机中存储、组织数据的方式,通常情况下,精心选择的数据结构可以带来最有效的算法;
3、数据结构是抽象数据类型的物理实现
数据结构的实现离不开算法,算法Algorithm,单词意思为解决问题的方法和步骤
算法的定义:
1、一个有限指令集,每条指令的描述不依赖于语言
2、接受一些输入(有时不需要输入)
3、产生输出
4、一定有限步骤后终止
常用的数据结构
八种:栈、队列、链表、集合、字典、树、图、哈希表
每一种都有其对应的应用场景, 不同的数据结构的不同操作性能是不同的:
-
有的查询性能很快,有的插入速度很快,有的是插入头和尾速度很快
-
有的做范围查找很快,有的允许元素重复,有的不允许重复等等
-
在开发中如何选择,要根据具体的需求来选
在学习数据结构后,可根据业务需求选择响应的数据结构,数据结构是每一个程序员都应该学习的课程, 数据结构和语言无关, 基本常见的编程语言都有直接或者间接的使用上述常见的数据结构。
今天讲解栈和队列
栈
栈的基本特性:
1、与数组相似,但它是一种受限制的线性结构
2、看作存取数据的一个容器,只能在容器的一端操作数据
3、LIFO(last in first out ),表示先进后出,意思就是第一个进去的元素,只能在最后一个出来
4、向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素
5、从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
简单画出简图:
在前端中简单实现对栈的操作:
用es6新增的class类封装栈的常用操作:
push()向栈顶添加一个元素;
pop()移除栈顶元素,并返回这个值;
peek()返回栈顶元素;
isEmpty()返回布尔值,栈内无任何元素返回true,否则返回false;
clear()清除栈内的所有元素
size()返回栈内元素的个数
代码实例:
class Stack{
constructor(){
this.item=[]
}
//入栈
push(i){
this.item.push(i)
}
//出栈 删除最后一个元素并返回
pop(){
return this.item.pop()
}
//peek 返回最后一个元素
peek(){
return this.item[this.item.length-1]
}
//isEmpty是否为空
isEmpty(){
return this.item.length==0
}
// clear清空栈
clear(){
this.item=[]
}
//栈内元素的个数
size(){
return this.item.length
}
}
实际应用:利用栈实现十进制转换为二进制
class Stack{
constructor(){
this.item=[]
}
//入栈
push(i){
this.item.push(i)
}
//出栈 删除最后一个元素并返回
pop(){
return this.item.pop()
}
//peek 返回最后一个元素
peek(){
return this.item[this.item.length-1]
}
//isEmpty是否为空
isEmpty(){
return this.item.length==0
}
// clear清空栈
clear(){
this.item=[]
}
//栈内元素的个数
size(){
return this.item.length
}
}
function bin(el){
var stack=new Stack()
// console.log(stack);
//余数
while(el>0){
let yushu=el%2
stack.push(yushu)
el=Math.floor(el/2)
}
console.log(stack.item.length);
var str=""
while(stack.isEmpty()==false){
str=str+stack.item.pop()
}
return str
}
console.log(bin(8)); //打印结果1000
队列
队列也是受限制的线性表,它的基本特性:
FIFO先进先出,意思就是先进入队列的元素先出去;
在队列前端删除元素,在后端插入元素。
画出简图:
在生活中很多例子都像队列,例如食堂排队打饭,先来排队的人,优先打到饭离开。
队列的常见操作:
enqueue()向队列尾部添加一个新的元素;
delqueue()移除队列中队首的那个元素;
front()返回队列队首的那个元素;
isEmpty()返回布尔值,如果队列不含任何元素返回true,反之false;
size()返回队列包含元素的个数。
代码实现:
//封装一个队列
class Queue{
constructor(){
this.item=[]
}
//入队
enqueue(el){
this.item.push(el)
}
//出队
delqueue(){
return this.item.shift()
}
// 返回首元素
front(){
return this.item[0]
}
//判空
isEmpty(){
return this.item.length==0
}
//元素个数
size(){
return this.item.length
}
}
通过队列来实现一个击鼓传花的小游戏,每次数到3的人被淘汰,下一个人又从1开始数。
function jigu(arr){
//创建队列
var queue= new Queue()
//入队
arr.forEach(el => {
queue.enqueue(el)
});
//数数
let count=1
while(queue.size()>1){
if(count<3){
queue.enqueue(queue.delqueue)
count++
}else{
//等于3时
queue.delqueue()
count=1
}
}
return queue.front()
}
var arr=["鲨鱼辣椒","蜻蜓队长", "嶂螂恶霸", "金龟次郎", "蜗了莱莱","铁甲小宝"]
console.log(jigu(arr)); //鲨鱼辣椒
此外,我们还需要认识一种队列——优先级队列,普通的队列插入一个元素, 数据会被放在后端, 并且需要前面所有的元素都处理完成后才会处理前面的数据。在有些情况下,元素是要插队的,插入的元素与已存在队列的元素进行优先级比较,将元素插入到正确的位置。
队列优先级的实现:
实现思路:添加元素时,如果队列内无元素,则直接添加;如果有,将当前的优先级和队列中已经存在的元素优先级进行比较, 以获得自己正确的位置。
class Node{
constructor(el,priority){
this.data=el,
this.priority=priority
}
}
class PriorityQueue{
constructor(){
this.item=[]
}
enqueue(el,priority){
//创建新节点 或者直接赋值 let newnode={data:el,priority:priority}
let newnode=new Node(el,priority)
if(this.item.length==0){
//空队列
this.item.push(newnode)
}else{
let isAdd=false
//非空队列
for (let i = 0; i < this.item.length; 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("qqq",10)
pq.enqueue("qqq",100)
pq.enqueue("qqq",101)
console.log(pq.item);