C++栈链的实现(链式栈)

栈链与栈的区别

1. 基本概念
  • 栈(Stack)
    是一种抽象数据类型(ADT),遵循后进先出(LIFO)原则,核心操作包括 push(压栈)、pop(弹栈)、peek(查看栈顶)。

  • 链式栈(Linked Stack,或“栈链”)
    是栈的具体实现方式,使用链表(动态节点链接)存储数据,通过指针管理栈顶元素。

    2. 核心区别
    对比项栈(抽象概念)链式栈(具体实现)
    存储结构可以是数组或链表必须基于链表
    容量限制数组实现有固定大小;链表实现无固定限制动态分配内存,无固定容量限制
    内存占用数组实现可能浪费空间按需分配内存,空间利用率高
    操作时间复杂度push/pop 均为 O(1)(数组或链表)push/pop 均为 O(1)(仅链表头操作)
    适用场景需要快速随机访问时用数组;否则用链表适合频繁动态扩容的场景

    3. 链式栈的优势
  • 动态扩容:无需预先分配固定内存,避免栈溢出。

  • 内存高效:按需分配节点,节省未使用空间。

  • 实现灵活:插入/删除仅需调整指针,适合高频操作。

程序功能分析

该程序实现了一个链式栈(Linked Stack),支持以下操作:

  • 压栈(push):将元素添加到栈顶。

  • 弹栈(pop):移除并返回栈顶元素。

  • 判空(isempty):检查栈是否为空。

  • 查看栈顶(peek):返回栈顶元素的值(不删除)。

  • 打印所有元素(printstack):按栈顶到栈底的顺序输出元素。


程序结构分析

  1. 头文件(LinkStack.h)

    • 定义模板类 linkstack<T>,支持泛型数据类型。

    • 节点结构体 Node

      • 包含数据成员 m_data 和指向下一节点的指针 m_next

      • 构造函数直接初始化数据与指针。

    • 栈核心逻辑

      • 栈顶指针 topNode 初始化为 nullptr

      • 通过动态分配节点实现链式存储。

  2. 源文件(LinkStack.cpp)

    • 主函数测试链栈功能:

      • 压入 167789

      • 检查栈是否为空(输出“有值”)。

      • 打印栈内所有元素(预期输出:89 -> 77 -> 16 -> null)。


函数实现思路

  1. 初始化栈:
    struct Node {
    	T m_data;//节点数据
    	Node* m_next;//next指针,指向下一个节点
    	Node(T data,Node *next):m_data(data),m_next(next) {};//结构体的构造函数(数据,尾指针指向下一个节点)
    };
    Node* topNode;//栈顶指针

    定义一个结构体实现栈的定义,链式栈是以节点为单位,每个节点包含data值和next指针指向下一个节点,因为是栈结构,遵循后进先出的原则,栈顶指针指向头节点。

  2. 压栈(push)
    • 创建新节点,新节点的 m_next 指向当前栈顶 topNode

    • 更新 topNode 为新节点,时间复杂度为 O(1)

      void push(const T &val) {
      	Node *newnode= new Node(val,topNode);//创建一个新节点,栈顶节点原来指向的是新节点的next的位置,所以创建的时候把topnode的位置转给新节点的next来指向
      	topNode = newnode;//将原来的栈顶指针指向新的节点
      }

  3. 弹栈(pop)
    • 若栈非空,保存栈顶数据,将 topNode 指向下一节点,删除原栈顶节点。

    • 若栈空,返回 0(可能不适用于非整型数据),时间复杂度为 O(1)

      T pop() {
      	if (isempty()) {
      		cout << "栈已空" << endl;
      		return 0;
      	}
          //创建一个临时指针指向要pop的节点
      	Node* temp = topNode;
      	//把节点内的数据取出来保存
      	T val = temp->m_data;
      	//把栈顶指针挪到下一个位置,原来的准备删除
      	topNode = topNode->m_next;
      	//删除原来的栈顶节点
      	delete temp;
      	return val;//返回保存的数据
      }

  4. 判空(isempty)
    • 直接检查 topNode 是否为 nullptr,时间复杂度 O(1)

      bool isempty() {
      	if (topNode == nullptr) { return true; }
      	else
      	{
      		return false;
      	}
      }

  5. 查看栈顶(peek)
    • 若栈非空,返回 topNode->m_data

    • 问题:栈空的情况下按照正常情况需要抛出异常,但我懒得弄,就用了return 0取代,这里注意一下。

      //返回栈顶元素的值
      T peek() {
      	if (isempty()) {
      		cout << "栈已空" << endl;
      		return;
      	}
      	return topNode->m_data;
      }

  6. 打印元素(printstack)
    • 遍历栈顶到栈底,用 -> 连接元素,时间复杂度 O(n)

      //遍历所有栈内元素
      void printstack() {
      	
      		Node* ptr = topNode;
      		cout << "所有的栈元素:";
      		
      		
      			while (ptr != nullptr)
      			{
      				cout << ptr->m_data;
      				if (ptr->m_next != nullptr) {
      					
      					cout << " -> ";
      				}
      				ptr = ptr->m_next;
      				
      			}
      			cout << " ->null " << endl;
      	}

 总结

  • 栈是逻辑模型:定义操作规则(LIFO),与具体实现无关。

  • 链式栈是物理实现:用链表动态管理数据,解决固定容量问题。

  • 核心选择依据:根据场景需求选择数组栈(快速访问)或链式栈(动态灵活)。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值