C++算法系列-栈与队列

简介: 笔记

在学完链表后,接下来我们就开始学习栈和队列了,因为栈与队列的实现是基于链表的(也可以是数组),所以要先学链表,然后紧接着学栈与队列。


一. 栈(链表实现)


1. 栈的简介

在生活中,我们会碰到这样一种情况,在往球桶里面放球的时候,最先放进去的球,只能在最后取出。

为了模拟上述的情况,于是就出现了栈这种数据结构。

一般栈可以就行如下操作

入栈push,往栈里面存放元素。

出栈pop,取出栈的顶部元素。

清空栈pop_all,将栈里面的全部元素都出栈。

判断栈是否为空。

返回栈的顶部元素,但不出栈。

2. 栈的实现

1.入栈

void push(int i)
  {
    Node* q = new Node;
    q->data = i;
    if (tail != NULL)
    {
      q->next = tail;
      tail = q;
    }
    else
    {
      tail = q;
      q->next = NULL;
    }
  }

2.出栈

bool pop()
  {
    if (tail != NULL)
    {
      Node*q = tail;
      tail = tail->next;
      delete q;
      return true;
    }
    else
      return false;
  }

判断栈是否为空

bool empty()
  {
  if (tail != NULL)
    return false;
  else
    return true;
  }


返回顶部元素

int top()
  {
  if (tail != NULL)
    return tail->data;
  else
    return 0;
  }


清空栈

void pop_all()
  {
  Node * p = tail, *q;
  while (p->next)
  {
    q = p->next;
    delete p;
    p = q;
  }
  delete p;
  tail = NULL;
  }


完整实现

#include<iostream>
using namespace std;
class Node
{
public:
  int data;
  Node *next;
};
class Stack {
private:
  Node  *tail;
public:
  Stack()
  {
  tail = NULL;
  }
  Stack(int i)
  {
  Node *q = new Node;
  q->data = i;
  tail = q;
  q->next = NULL;
  }
  ~Stack()
  {
  Node * p = tail, *q;
  while (p)
  {
    q = p->next;
    delete p;
    p = q;
  }
  delete p;
  }
  //入栈
  void push(int i)
  {
  Node* q = new Node;
  q->data = i;
  if (tail != NULL)
  {
    q->next = tail;
    tail = q;
  }
  else
  {
    tail = q;
    q->next = NULL;
  }
  }
  //出栈
  bool pop()
  {
  if (tail != NULL)
  {
    Node*q = tail;
    tail = tail->next;
    delete q;
    return true;
  }
  else
    return false;
  }
  //返回顶部元素
  int top()
  {
  if (tail != NULL)
    return tail->data;
  else
    return 0;
  }
  //判断栈是否为空
  bool empty()
  {
  if (tail != NULL)
    return false;
  else
    return true;
  }
  //清空栈
  void pop_all()
  {
  Node * p = tail, *q;
  while (p->next)
  {
    q = p->next;
    delete p;
    p = q;
  }
  delete p;
  tail = NULL;
  }
};


二. 队列


1. 队列简介

在日常中,我们又会遇到另外一种非常常见的情况,那就是排队。在排队的时候,最先来的,业务就可以就先处理完。

在这种情况下,我们就使用队列这种数据结构来模拟这种情况。

队列一般可以进行的操作。

clear清空队列

isEmpty判断队列是否为空

enqueue在队列尾部加入元素

dequeue取出队列的第一个元素

firstE返回队列的第一个元素,但不删除

2. 队列的实现

完整代码,基于库中的列表

#include<list>
template<class T>
class Queue {
private:
  list<T> lst;
public:
  Queue()
  {
  }
  void clear()
  {
  lst.clear();
  }
  bool isEmpty() const {
  return lst.empty();
  }
  T& front()
  {
  return lst.front();
  }
  T dequeue()
  {
  T e1 = lst.front();
  lst.pop_front();
  return e1;
  }
  void enqueue(const T& e1)
  {
  lst.push_back(e1);
  }
};



三. 课后习题


将栈S中的元素的顺序倒过来

1-a 使用两个额外的栈

int main()
{
  stack<int > q1;
  stack<int > q2;
  stack<int > q3;
  q1.push(1);
  q1.push(2);
  q1.push(3);
  q2.push(q1.top());
  q1.pop();
  q2.push(q1.top());
  q1.pop();
  q2.push(q1.top());
  q1.pop();
  q3.push(q2.top());
  q2.pop();
  q3.push(q2.top());
  q2.pop();
  q3.push(q2.top());
  q2.pop();
  q1.push(q3.top());
  q3.pop();
  q1.push(q3.top());
  q3.pop();
  q1.push(q3.top());
  q3.pop();
  while (!q1.empty())
  {
  cout << q1.top();
  q1.pop();
  }
  return 0;
}

1-b 使用额外的一个队列


int main()
{
  stack<int> q;
  list<int> m;
  q.push(1);
  q.push(2);
  q.push(3);
  while (!q.empty())
  {
  m.push_back(q.top());
  q.pop();
  }
  while (!m.empty())
  {
  q.push(m.front());
  m.pop_front();
  }
  while (!q.empty())
  {
  cout << q.top();
  q.pop();
  }
  return 0;
}


1-c 使用额外的一个栈和几个额外的非数组变量

int main()
{
  stack<int> q;
  stack<int> q2;
  q.push(1);
  q.push(2);
  q.push(3);
  while (!q.empty())
  {
  q2.push(q.top());
  q.pop();
  }
  q.swap(q2);
  while (!q.empty())
  {
  cout << q.top();
  q.pop();
  }
}

使用一个额外的栈和几个额外的非数组变量,将栈S中的元素按升序排列

int main()
{
  stack<int> q;
  stack<int> q2;
  int a=0, b=0,c = -10, min = 9999;
  q.push(2), q.push(5), q.push(1),q.push(4),q.push(7),q.push(10),q.push(8),q.push(3);
  for (int i = 0; i < 7; i++)
  {
  min = 999;
  while (!q.empty())
  {
    if (q.top() == c)
    break;
    if (q.top() < min)
    min = q.top();
    q2.push(q.top());
    q.pop();
  }
  c =min;
  q.push(min);
  while (!q2.empty())
  {
    if (q2.top() == min)
    {
    q2.pop();
    continue;
    }
    q.push(q2.top());
    q2.pop();
  }
  b = 0;
  }
  while (!q.empty())
  {
  cout << q.top()<<" ";
  q.pop();
  }
  return 0;
}

将栈S1中的元素转换到栈S2中,使S2中元素的顺序与S1中元素的顺序相同

3-a 使用一个额外的栈

int main()
{
  stack<int> S1;
  stack<int> S2;
  stack<int> q;
  S1.push(2), S1.push(3), S1.push(4), S1.push(5);
  while (!S1.empty())
  {
  q.push(S1.top());
  S1.pop();
  }
  while (!q.empty())
  {
  S2.push(q.top());
  q.pop();
  }
  while (!S2.empty())
  {
  cout << S2.top() << " ";
  S2.pop();
  }
  return 0;
}


3-b 不使用额外的栈,只使用几个额外的非数组变量


int main()
{
  stack<int> S1, S2;
  int a, b=0, c = 1, d;
  S1.push(1);
  S1.push(2);
  S1.push(3);
  S1.push(4);
  a = S1.size();
  while (a)
  {
  // 写出 i<S1.size() - 1 会出现错误
  for (int i = 0; i <a - c; i++)
  {
    S2.push(S1.top());
    S1.pop();
  }
  d = S1.top();
  S1.pop();
  for (int i = 0; i < 3-b; i++)
  {
    S1.push(S2.top());
    S2.pop();
  }
  S2.push(d);
  b++;
  a--;  
  }
  while (!S2.empty())
  {
  cout << S2.top() << " ";
  S2.pop();
  }
  return 0;
}

使用额外的非数组变量及下面的条件,将队列中的所有元素排序

5-a 两个额外的队列

int main()
{
  queue<int> q1 , q2, q3;
  q1.push(4), q1.push(1), q1.push(7), q1.push(10), q1.push(2), q1.push(6), q1.push(8);
  int min;
  int a = q1.size();
  for (int i = 0; i < a; i++)
  {
  min = 999;
  while (!q1.empty())
  {
    if (q1.front() < min)
    {
    min = q1.front();
    }
    q2.push(q1.front());
    q1.pop();
  }
  while (!q2.empty())
  {
    if (q2.front() == min)
    {
    q2.pop();
    continue;
    }
    q1.push(q2.front());
    q2.pop();
  } 
  q3.push(min);
  }
  while (!q3.empty())
  {
  cout << q3.front()<<" " ;
  q3.pop();
  }
  return 0;
}

以上就是栈和队列的大部分内容。

ps:以上知识学习于《C++数据结构与算法》Adam Drozdek 著, 徐丹,吴伟敏 译。

Thank for your reading !!!


公众号:FPGA之旅




目录
相关文章
|
10月前
|
存储 监控 算法
基于 C++ 哈希表算法实现局域网监控电脑屏幕的数据加速机制研究
企业网络安全与办公管理需求日益复杂的学术语境下,局域网监控电脑屏幕作为保障信息安全、规范员工操作的重要手段,已然成为网络安全领域的关键研究对象。其作用类似网络空间中的 “电子眼”,实时捕获每台电脑屏幕上的操作动态。然而,面对海量监控数据,实现高效数据存储与快速检索,已成为提升监控系统性能的核心挑战。本文聚焦于 C++ 语言中的哈希表算法,深入探究其如何成为局域网监控电脑屏幕数据处理的 “加速引擎”,并通过详尽的代码示例,展现其强大功能与应用价值。
209 2
|
12月前
|
存储 算法 数据处理
公司局域网管理中的哈希表查找优化 C++ 算法探究
在数字化办公环境中,公司局域网管理至关重要。哈希表作为一种高效的数据结构,通过哈希函数将关键值(如IP地址、账号)映射到数组索引,实现快速的插入、删除与查找操作。例如,在员工登录验证和设备信息管理中,哈希表能显著提升效率,避免传统线性查找的低效问题。本文以C++为例,展示了哈希表在局域网管理中的具体应用,包括设备MAC地址与IP分配的存储与查询,并探讨了优化哈希函数和扩容策略,确保网络管理高效准确。
|
10月前
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
247 17
|
8月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
210 0
|
9月前
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
266 0
|
11月前
|
存储 监控 算法
基于 C++ 哈希表算法的局域网如何监控电脑技术解析
当代数字化办公与生活环境中,局域网的广泛应用极大地提升了信息交互的效率与便捷性。然而,出于网络安全管理、资源合理分配以及合规性要求等多方面的考量,对局域网内计算机进行有效监控成为一项至关重要的任务。实现局域网内计算机监控,涉及多种数据结构与算法的运用。本文聚焦于 C++ 编程语言中的哈希表算法,深入探讨其在局域网计算机监控场景中的应用,并通过详尽的代码示例进行阐释。
220 4
|
12月前
|
存储 算法 安全
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
255 8
|
5月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
503 0
|
5月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
330 2
|
6月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
308 3