数据结构学习⑤--栈和队列

本文探讨了栈的后进先出特性,数组和链表的实现方式,以及它们在递归、深度优先搜索、表达式求值和操作系统管理中的作用。同时,深入剖析了队列的先进先出特性和优先队列的应用,涉及广度优先搜索、消息队列和资源管理。通过实例演示如何用栈实现特殊顺序读取和合并优先级链表,以及滑动窗口最大值问题的解决方案。
摘要由CSDN通过智能技术生成

理论基础

栈 --后进先出的线性表

栈顶元素:

唯一可访问的元素

入栈顺序和出栈顺序正好相反

栈的储存形式

数组实现: 顺序表的简化版

链表实现:用单链表方式存储,其中指针的方向是从栈顶向下链接

用途:

栈常用来处理递归结果的数据

  •  深度优先搜索
  • 表达式求值
  • 操作系统函数调用的管理

队列:

先进先出的线性表 (两次后进先出等于一次先进先出)

优先队列(最大/最小堆值)

头尾元素: 

队头: 删除操作

对尾: 插入操作

队列操作:

入队列: enQueue

出队列: deQueue

取队首元素: getFront

判断队列是否为空: isEmpty

队列的储存方式: 

数组实现: 环形数组

链表实现: 用单链表方式存储, 队列中每个元素对于链表中的每一个节点

溢出处理 

上溢(Overflow)

下溢(Underflow)

 用途:

  • 广度优先搜索
  • 消息缓冲器
  • 计算机的硬件设备之间的通信缓冲
  • 操作系统的资源管理(优先管理)

 题目: 

1. 实现特殊顺序读取:

  • "倾倒"实现特殊顺序
  • 升序,将序排列
  • 力扣高频题: 20,42, 173, 224,84, 239, 316, 402 

用栈实现队列  Leetcode_232 难度:简单

这题基本没难点, peek的定义是

Stack. peek() method in Java is used to retrieve or fetch the first element of the Stack or the element present at the top of the Stack

而在c++里,根据cpp reference,似乎只有用top来取第一个元素,用pop来去除第一个元素

 class MyQueue {
public:
    stack<int> src_stk;
    /** Initialize your data structure here. */
    MyQueue() {
        //stack<int> src_stk;
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        src_stk.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        stack<int> tmp_stk;
        while(!src_stk.empty())
        {
            int head = src_stk.top();
            src_stk.pop();
            tmp_stk.push(head);
        }
        int rtn_val = tmp_stk.top();
        tmp_stk.pop();
        while(!tmp_stk.empty())
        {
            int head = tmp_stk.top();
            tmp_stk.pop();
            src_stk.push(head);
        }
        return rtn_val;
    }
    
    /** Get the front element. */
    int peek() {
        stack<int> tmp_stk;
        while(!src_stk.empty())
        {
            int head = src_stk.top();
            src_stk.pop();
            tmp_stk.push(head);
        }
        int rtn_val = tmp_stk.top();
        while(!tmp_stk.empty())
        {
            int head = tmp_stk.top();
            tmp_stk.pop();
            src_stk.push(head);
        }
        return rtn_val;
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return (src_stk.empty());
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

 2. 次序问题:

  • 元素具有优先级
  • 动态排序
  • 力扣高频题: 215, 347, 252, 253, 23

合并K个升序链表  Leetcode_23

本题比较直接或者naive的方法是: 对于每个链表的头部进行遍历和更新,保证始终把所有链表中最小的第一个元素加入新的链表中, 然后, 对于该链表头进行更新.

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        vector<ListNode*> cur_list;
        
        // for(int i=0;i<lists.size();i++)
        // {
        //     cur_list.push_back(lists[i]);
        // }
        //get the smallest node
        int cur_idx=-1;
        bool is_empty=true;
        ListNode* pre_node = new ListNode;
        ListNode* cur_node = pre_node;
        int min_val = 10000;
        while(1&&lists.size())
        {
        for(int i=0;i<lists.size();i++)
        {
            if(lists[i])
            {
                is_empty= false;
                if(lists[i]->val<min_val)
                {
                    min_val= lists[i]->val;
                    cur_idx = i;
                    //cout<<"idx "<<i<<endl;
                }
            }
            
            if (i==lists.size()-1)
                {
                    if(is_empty)
                    {
                        return pre_node->next; 
                        //break;
                    }
                    else
                    {
                        ListNode* tmp_node= lists[cur_idx];
                        lists[cur_idx]=lists[cur_idx]->next;
                        cur_node->next = tmp_node;
                        cur_node = cur_node->next;
                        is_empty=true;
                        min_val =10000;
                    }
                }
            }
        }

        return pre_node->next; 
    }
};

更高级的方法是使用mergesort,leetcode上有对应题解.

滑动窗口最大值 Leetcode_239

这题应用到了Priority queue这一数据结构.它的使用可以大大简化做题难度

深度优先和广度优先算法

  • 深度优先: 栈
  • 广度优先: 队列
  • 力扣高频题: 102

栈和队列的C++标准库实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值