数据结构——栈&队列

本文介绍了数据结构的基础概念,包括栈、队列和优先级队列的特性及应用场景。通过JavaScript ES5和ES6实现了栈和队列的数据结构,展示了它们在进制转换和游戏模拟中的应用。此外,还讲解了优先级队列的原理,通过示例展示了如何在队列中考虑元素的优先级。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、数据结构

概念:

  • 数据结构(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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈ha~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值