当前位置: 首页 > news >正文

【数据结构】链栈的基本操作

目录

一、链栈基础结构

二、核心操作算法详解

1. 初始化栈(InitStack)

2. 判断栈是否为空(StackEmpty)

3. 求栈的长度(StackLength)

4. 进栈操作(Push)

5. 出栈操作(Pop)

6. 取栈顶元素(GetTop)

7. 清空栈(ClearStack)

8. 销毁栈(DestroyStack)

9. 遍历栈(TraverseStack)

10. 复制栈(CopyStack)

11. 判断两个栈是否相等(StackEqual)

12. 逆置栈(ReverseStack)

三、链栈的基本操作的完整代码展示

(一)C++代码

(二)Python代码

(三)Java代码

四、程序运行结果展示

(一)C++程序运行截图

(二)Python程序运行截图

(三)Java程序运行截图

五、总结


一、链栈基础结构

链栈是用链表实现的栈(先进后出,LIFO),核心结构是StackNode节点和LinkStack栈顶指针:

typedef struct StackNode {SElemType data;          // 数据域:存储栈元素struct StackNode *next;  // 指针域:指向后一个节点(栈底方向)
} StackNode, *LinkStack;     // LinkStack本质是指向StackNode的指针(栈顶指针)
  • 栈顶指针S指向栈中最顶部的节点(最后入栈的元素)
  • 空栈时,S = NULL(无任何节点)
  • 元素入栈 / 出栈仅在栈顶操作(链表头部),符合栈 "先进后出" 特性

二、核心操作算法详解

1. 初始化栈(InitStack)

功能:创建一个空栈算法步骤

  1. 将栈顶指针S直接置为NULL
  2. 此时栈中无任何节点,即为空栈

代码解析

void InitStack(LinkStack &S) {S = NULL;  // 栈顶指针置空,代表空栈
}

复杂度

  • 时间复杂度:O (1)(仅需一次指针赋值)
  • 空间复杂度:O (1)(无额外空间占用)注意:初始化后必须调用此函数,否则栈顶指针可能为随机值,导致后续操作出错。
2. 判断栈是否为空(StackEmpty)

功能:检查栈中是否有元素算法步骤

  1. 检查栈顶指针S是否为NULL
  2. S == NULL,返回true(空栈);否则返回false(非空栈)

代码解析

bool StackEmpty(LinkStack S) {return (S == NULL);  // 栈顶指针为空 → 空栈
}

复杂度

  • 时间复杂度:O (1)(仅需一次指针比较)
  • 空间复杂度:O (1)注意:几乎所有栈操作前都需要先判断栈是否为空(如出栈、取栈顶),避免对空栈操作导致错误。
3. 求栈的长度(StackLength)

功能:计算栈中元素的个数算法步骤

  1. 初始化计数器length = 0,创建临时指针p并指向栈顶S
  2. 循环遍历链表:当p != NULL时,计数器length++p移动到下一个节点(p = p->next
  3. 遍历结束后,length即为栈的长度

代码解析

int StackLength(LinkStack S) {int length = 0;LinkStack p = S;  // 临时指针,从栈顶开始遍历while (p != NULL) {length++;       // 计数当前节点p = p->next;    // 移动到下一个节点(栈底方向)}return length;
}

复杂度

  • 时间复杂度:O (n)(n 为栈长度,需遍历所有节点)
  • 空间复杂度:O (1)(仅用一个临时指针)注意:链栈无法像顺序栈那样直接通过数组下标获取长度,必须遍历链表。
4. 进栈操作(Push)

功能:将元素e插入栈顶(成为新的栈顶元素)算法步骤

  1. 创建新节点pnew StackNode
  2. 新节点数据域赋值:p->data = e
  3. 新节点指针域指向原栈顶:p->next = S(原栈顶成为新节点的下一个节点)
  4. 更新栈顶指针:S = p(新节点成为新的栈顶)

代码解析

void Push(LinkStack &S, SElemType e) {LinkStack p = new StackNode;  // 1. 创建新节点p->data = e;                  // 2. 存入数据p->next = S;                  // 3. 新节点指向原栈顶S = p;                        // 4. 更新栈顶为新节点
}

示意图

原栈:S → A → B → NULL(栈顶为A)
进栈e后:
S → e → A → B → NULL(栈顶为e)

复杂度

  • 时间复杂度:O (1)(仅需 4 步指针操作,无需遍历)
  • 空间复杂度:O (1)(仅创建一个新节点)注意:进栈是链栈的核心操作,利用链表头部插入的特性实现,效率极高。
5. 出栈操作(Pop)

功能:移除栈顶元素,并返回该元素的值算法步骤

  1. 先判断栈是否为空(StackEmpty(S)):若为空,输出错误信息,返回特殊值(如 - 1)
  2. 若栈非空,创建临时指针p指向栈顶S(暂存栈顶节点)
  3. 取出栈顶元素值:e = p->data
  4. 更新栈顶指针:S = S->next(原栈顶的下一个节点成为新栈顶)
  5. 释放原栈顶节点的内存(delete p),避免内存泄漏
  6. 返回取出的元素值e

代码解析

SElemType Pop(LinkStack &S) {if (StackEmpty(S)) {  // 1. 检查空栈cerr << "错误:栈为空,无法执行出栈操作!" << endl;return -1;}LinkStack p = S;      // 2. 暂存栈顶节点SElemType e = p->data;// 3. 取出栈顶元素S = S->next;          // 4. 更新栈顶指针delete p;             // 5. 释放内存return e;             // 6. 返回元素
}

示意图

原栈:S → e → A → B → NULL(栈顶为e)
出栈后:
S → A → B → NULL(栈顶为A,e被移除并返回)

复杂度

  • 时间复杂度:O (1)(仅需几步指针操作)
  • 空间复杂度:O (1)(仅用一个临时指针)注意:出栈必须释放原栈顶节点的内存,否则会导致内存泄漏;空栈时必须报错,避免访问空指针。
6. 取栈顶元素(GetTop)

功能:获取栈顶元素的值(不改变栈结构,元素仍在栈中)算法步骤

  1. 判断栈是否为空:若为空,输出错误信息,返回特殊值
  2. 若栈非空,直接返回栈顶节点的数据(S->data

代码解析

SElemType GetTop(LinkStack S) {if (StackEmpty(S)) {  // 检查空栈cerr << "错误:栈为空,无栈顶元素!" << endl;return -1;}return S->data;       // 返回栈顶元素值
}

复杂度

  • 时间复杂度:O (1)(直接访问栈顶节点)
  • 空间复杂度:O (1)与出栈的区别:取栈顶仅读取元素,不改变栈结构;出栈会移除元素并修改栈结构。
7. 清空栈(ClearStack)

功能:删除栈中所有元素,但保留栈的结构(最终为一个空栈)算法步骤

  1. 创建两个临时指针pqp初始指向栈顶S
  2. 循环遍历所有节点:
    • q = p(暂存当前节点)
    • p = p->nextp移动到下一个节点)
    • delete q(释放当前节点内存)
  3. 遍历结束后,将栈顶指针S置为NULL(此时栈为空)

代码解析

void ClearStack(LinkStack &S) {LinkStack p, q;p = S;while (p != NULL) {q = p;          // 暂存当前节点p = p->next;    // 移动到下一个节点delete q;       // 释放当前节点}S = NULL;  // 栈顶指针置空,成为空栈
}

复杂度

  • 时间复杂度:O (n)(需遍历并释放所有节点)
  • 空间复杂度:O (1)(仅用两个临时指针)与销毁栈的区别:清空栈后,栈仍可继续使用(可重新进栈);销毁栈的逻辑与清空栈一致(链栈无额外结构),但语义上代表栈生命周期结束。
8. 销毁栈(DestroyStack)

功能:释放栈占用的所有内存,结束栈的生命周期算法步骤

  1. 直接调用ClearStack(S)(释放所有节点内存,并将S置为NULL
  2. 链栈无额外的容器结构(如顺序栈的数组),因此无需其他操作

代码解析

void DestroyStack(LinkStack &S) {ClearStack(S);  // 释放所有节点,栈顶指针置空
}

复杂度

  • 时间复杂度:O (n)(同 ClearStack)
  • 空间复杂度:O (1)注意:销毁后若需使用栈,必须重新调用InitStack初始化。
9. 遍历栈(TraverseStack)

功能:从栈顶到栈底依次打印所有元素算法步骤

  1. 判断栈是否为空:若为空,输出提示信息
  2. 若栈非空,创建临时指针p指向栈顶S
  3. 循环遍历:当p != NULL时,打印p->datap移动到下一个节点(p = p->next
  4. 遍历结束后换行

代码解析

void TraverseStack(LinkStack S) {if (StackEmpty(S)) {cout << "栈为空,无元素可遍历!" << endl;return;}cout << "链栈元素(从栈顶到栈底):";LinkStack p = S;while (p != NULL) {cout << p->data << " ";  // 打印当前元素p = p->next;             // 移动到下一个节点(栈底方向)}cout << endl;
}

示例:栈中元素(从栈顶到栈底)为50,40,30,20,10,遍历后输出:链栈元素(从栈顶到栈底):50 40 30 20 10

复杂度

  • 时间复杂度:O (n)(需遍历所有节点)
  • 空间复杂度:O (1)
10. 复制栈(CopyStack)

功能:将栈S的所有元素复制到栈T,复制后TS的元素顺序完全一致(栈顶到栈底元素相同)算法步骤

  1. 若目标栈T非空,先调用ClearStack(T)清空T(避免内存泄漏)
  2. 若源栈S为空,将T置为NULL,返回true
  3. S非空,创建辅助栈temp并初始化
  4. 遍历源栈S,将所有元素依次压入辅助栈temp(此时temp的元素是S的逆序,因为栈是先进后出)
  5. 遍历辅助栈temp,将所有元素依次弹出并压入目标栈T(此时T的元素顺序与S完全一致)
  6. 返回true

代码解析

bool CopyStack(LinkStack S, LinkStack &T) {if (T != NULL) {ClearStack(T);  // 1. 先清空目标栈}if (StackEmpty(S)) {  // 2. 源栈为空,目标栈也为空T = NULL;return true;}LinkStack temp;InitStack(temp);  // 3. 创建辅助栈LinkStack p = S;// 4. 将S的元素逆序存入tempwhile (p != NULL) {Push(temp, p->data);p = p->next;}// 5. 将temp的元素弹出并存入T,恢复原顺序while (!StackEmpty(temp)) {Push(T, Pop(temp));}return true;
}

示意图

源栈S:顶→50→40→30→底  
辅助栈temp:先存入50→40→30 → temp中顺序为顶→30→40→50→底  
目标栈T:从temp弹出30→40→50并压入 → T中顺序为顶→50→40→30→底(与S一致)

复杂度

  • 时间复杂度:O (n)(遍历Stemp各一次,共 2n 步)
  • 空间复杂度:O (n)(辅助栈temp需存储 n 个元素)关键逻辑:利用辅助栈反转顺序,确保复制后的栈与原栈元素顺序一致(若直接复制链表,T的元素会是S的逆序,不符合栈的特性)。
11. 判断两个栈是否相等(StackEqual)

功能:检查两个栈ST是否完全相等(元素数量相同,且对应位置元素的值相同)算法步骤

  1. 调用StackLength分别获取ST的长度,若长度不同,直接返回false
  2. 若长度相同,创建两个临时指针p(指向S顶)和q(指向T顶)
  3. 循环遍历两个栈:
    • p->data != q->data,返回false
    • pq分别移动到下一个节点(p = p->nextq = q->next
  4. 遍历结束后,返回true

代码解析

bool StackEqual(LinkStack S, LinkStack T) {// 1. 长度不同则不相等if (StackLength(S) != StackLength(T)) {return false;}LinkStack p = S, q = T;// 2. 逐个比较元素while (p != NULL && q != NULL) {if (p->data != q->data) {return false;}p = p->next;q = q->next;}return true;
}

复杂度

  • 时间复杂度:O (n)(求长度需 O (n),比较元素需 O (n),总 O (n))
  • 空间复杂度:O (1)(仅用两个临时指针)
12. 逆置栈(ReverseStack)

功能:反转栈中元素的顺序(原栈顶元素变为栈底,原栈底元素变为栈顶)算法步骤

  1. 若栈为空(StackEmpty(S))或只有 1 个元素(StackLength(S) == 1),无需逆置,直接返回
  2. 若栈有多个元素,创建三个指针:prev = NULL(前一个节点)、curr = S(当前节点)、next = NULL(下一个节点)
  3. 循环反转指针方向:
    • next = curr->next(保存当前节点的下一个节点)
    • curr->next = prev(当前节点的指针改为指向前一个节点)
    • prev = currprev移动到当前节点)
    • curr = nextcurr移动到下一个节点)
  4. 循环结束后,prev指向原栈底节点(新栈顶),更新栈顶指针S = prev

代码解析

void ReverseStack(LinkStack &S) {// 1. 空栈或单元素栈无需逆置if (StackEmpty(S) || StackLength(S) == 1) {return;}LinkStack prev = NULL;LinkStack curr = S;LinkStack next = NULL;// 2. 反转链表指针方向while (curr != NULL) {next = curr->next;  // 保存下一个节点curr->next = prev;  // 反转当前节点指针prev = curr;        // 移动prevcurr = next;        // 移动curr}S = prev;  // 3. 更新栈顶为原栈底
}

示意图

原栈:S→50→40→30→20→10→NULL(顶→50,底→10)  
反转指针后:  
10→20→30→40→50→NULL,S指向10  
逆置后栈:S→10→20→30→40→50→NULL(顶→10,底→50)

复杂度

  • 时间复杂度:O (n)(需遍历所有节点一次)
  • 空间复杂度:O (1)(仅用三个临时指针,原地反转)优势:相比 "用辅助栈逆置"(空间 O (n)),此算法通过反转链表指针实现原地逆置,空间效率更高。

三、链栈的基本操作的完整代码展示

(一)C++代码
#include <iostream>
#include <windows.h>  // 引入Windows系统头文件
using namespace std;// 定义栈元素类型
typedef int SElemType;// 链栈节点结构定义
typedef struct StackNode {SElemType data;          // 数据域struct StackNode *next;  // 指针域,指向后继节点
} StackNode, *LinkStack;// 函数声明
void InitStack(LinkStack &S);                  // 链栈的初始化
bool StackEmpty(LinkStack S);                  // 判断链栈是否为空
int StackLength(LinkStack S);                  // 求链栈的长度
void Push(LinkStack &S, SElemType e);          // 链栈进栈操作
SElemType Pop(LinkStack &S);                   // 链栈出栈操作
SElemType GetTop(LinkStack S);                 // 取链栈栈顶元素
void ClearStack(LinkStack &S);                 // 清空链栈(保留栈结构)
void DestroyStack(LinkStack &S);               // 销毁链栈(释放所有资源)
void TraverseStack(LinkStack S);               // 遍历链栈元素(从栈顶到栈底)
bool CopyStack(LinkStack S, LinkStack &T);     // 复制栈(将S复制到T)
bool StackEqual(LinkStack S, LinkStack T);     // 判断两个栈是否相等
void ReverseStack(LinkStack &S);               // 逆置链栈// 测试函数
int main() {SetConsoleOutputCP(CP_UTF8);  // 强制控制台使用UTF-8解析输出LinkStack S, T;// 初始化栈InitStack(S);InitStack(T);cout << "初始化链栈S后,栈是否为空:" << (StackEmpty(S) ? "是" : "否") << endl;// 进栈操作cout << "\n执行进栈操作:依次入栈 10, 20, 30, 40, 50" << endl;Push(S, 10);Push(S, 20);Push(S, 30);Push(S, 40);Push(S, 50);TraverseStack(S);cout << "栈S的长度:" << StackLength(S) << endl;// 复制栈操作cout << "\n复制栈S到栈T..." << endl;CopyStack(S, T);cout << "栈T的元素:";TraverseStack(T);cout << "栈S和栈T是否相等:" << (StackEqual(S, T) ? "是" : "否") << endl;// 逆置栈操作cout << "\n逆置栈S..." << endl;ReverseStack(S);cout << "逆置后栈S的元素:";TraverseStack(S);cout << "栈S和栈T是否相等:" << (StackEqual(S, T) ? "是" : "否") << endl;// 再次逆置恢复原顺序ReverseStack(S);cout << "再次逆置后栈S的元素:";TraverseStack(S);// 出栈和取栈顶操作cout << "\n执行出栈操作:" << endl;cout << "出栈元素:" << Pop(S) << endl;cout << "出栈元素:" << Pop(S) << endl;TraverseStack(S);cout << "当前栈顶元素:" << GetTop(S) << endl;cout << "当前栈S的长度:" << StackLength(S) << endl;// 清空栈操作cout << "\n清空栈S..." << endl;ClearStack(S);cout << "清空后栈S是否为空:" << (StackEmpty(S) ? "是" : "否") << endl;cout << "清空后栈S的长度:" << StackLength(S) << endl;// 测试栈Tcout << "\n栈T的元素:";TraverseStack(T);cout << "栈T的长度:" << StackLength(T) << endl;// 销毁栈cout << "\n销毁链栈..." << endl;DestroyStack(S);DestroyStack(T);cout << "销毁后,栈S是否为空:" << (StackEmpty(S) ? "是" : "否") << endl;cout << "销毁后,栈T是否为空:" << (StackEmpty(T) ? "是" : "否") << endl;return 0;
}// 链栈的初始化
void InitStack(LinkStack &S) {S = NULL;  // 栈顶指针置空,表示空栈
}// 判断链栈是否为空
bool StackEmpty(LinkStack S) {return (S == NULL);  // 栈顶指针为空则栈空
}// 求链栈的长度
int StackLength(LinkStack S) {int length = 0;LinkStack p = S;while (p != NULL) {length++;p = p->next;}return length;
}// 链栈进栈操作
void Push(LinkStack &S, SElemType e) {LinkStack p = new StackNode;  // 创建新节点p->data = e;                  // 存入数据p->next = S;                  // 新节点指向原栈顶S = p;                        // 更新栈顶指针为新节点
}// 链栈出栈操作
SElemType Pop(LinkStack &S) {if (StackEmpty(S)) {cerr << "错误:栈为空,无法执行出栈操作!" << endl;return -1;  // 栈空时返回特殊值}LinkStack p = S;              // 暂存栈顶节点SElemType e = p->data;        // 获取栈顶元素值S = S->next;                  // 更新栈顶指针delete p;                     // 释放原栈顶节点内存return e;                     // 返回出栈元素
}// 取链栈栈顶元素
SElemType GetTop(LinkStack S) {if (StackEmpty(S)) {cerr << "错误:栈为空,无栈顶元素!" << endl;return -1;  // 栈空时返回特殊值}return S->data;  // 返回栈顶元素值
}// 清空链栈(保留栈结构,仅清空元素)
void ClearStack(LinkStack &S) {LinkStack p, q;p = S;while (p != NULL) {q = p;p = p->next;delete q;}S = NULL;  // 栈顶指针置空
}// 销毁链栈(释放所有资源)
void DestroyStack(LinkStack &S) {ClearStack(S);  // 清空栈元素// 链栈无需额外销毁操作,因为栈本身是指针
}// 遍历链栈元素(从栈顶到栈底)
void TraverseStack(LinkStack S) {if (StackEmpty(S)) {cout << "栈为空,无元素可遍历!" << endl;return;}cout << "链栈元素(从栈顶到栈底):";LinkStack p = S;while (p != NULL) {cout << p->data << " ";p = p->next;}cout << endl;
}// 复制栈(将S复制到T)
bool CopyStack(LinkStack S, LinkStack &T) {if (T != NULL) {ClearStack(T);  // 先清空目标栈}if (StackEmpty(S)) {T = NULL;return true;}// 辅助栈用于临时存储元素(解决顺序问题)LinkStack temp;InitStack(temp);LinkStack p = S;// 先将S的元素逆序存入临时栈while (p != NULL) {Push(temp, p->data);p = p->next;}// 再将临时栈的元素存入T,恢复原顺序while (!StackEmpty(temp)) {Push(T, Pop(temp));}return true;
}// 判断两个栈是否相等(元素数量和对应位置元素都相同)
bool StackEqual(LinkStack S, LinkStack T) {// 长度不同则直接不相等if (StackLength(S) != StackLength(T)) {return false;}LinkStack p = S, q = T;while (p != NULL && q != NULL) {if (p->data != q->data) {return false;}p = p->next;q = q->next;}return true;
}// 逆置链栈(改变元素顺序)
void ReverseStack(LinkStack &S) {if (StackEmpty(S) || StackLength(S) == 1) {return;  // 空栈或只有一个元素无需逆置}LinkStack prev = NULL;LinkStack curr = S;LinkStack next = NULL;// 反转链表指针方向while (curr != NULL) {next = curr->next;  // 保存下一个节点curr->next = prev;  // 反转当前节点指针prev = curr;        // 移动prev到当前节点curr = next;        // 移动curr到下一个节点}S = prev;  // 更新栈顶指针
}
(二)Python代码
# 定义栈节点类
class StackNode:def __init__(self, data):self.data = data  # 数据域self.next = None  # 指针域,指向后继节点# 链栈初始化:返回空栈(None表示空栈)
def init_stack():return None# 判断链栈是否为空
def stack_empty(s):return s is None# 求链栈的长度
def stack_length(s):length = 0p = swhile p is not None:length += 1p = p.nextreturn length# 链栈进栈操作
def push(s, e):# 创建新节点p = StackNode(e)# 新节点指向原栈顶p.next = s# 更新栈顶指针为新节点return p# 链栈出栈操作
def pop(s):if stack_empty(s):print("错误:栈为空,无法执行出栈操作!", file=sys.stderr)return None, s  # 返回None表示出错,栈顶不变# 暂存栈顶节点p = s# 获取栈顶元素值e = p.data# 更新栈顶指针s = s.next# Python会自动回收内存,无需手动释放return e, s# 取链栈栈顶元素
def get_top(s):if stack_empty(s):print("错误:栈为空,无栈顶元素!", file=sys.stderr)return Nonereturn s.data# 清空链栈(保留栈结构,仅清空元素)
def clear_stack(s):# 遍历并释放所有节点(Python中无需手动释放,只需将栈顶置空)return None# 销毁链栈(释放所有资源)
def destroy_stack(s):# 链栈在Python中无需额外销毁操作,清空即可return clear_stack(s)# 遍历链栈元素(从栈顶到栈底)
def traverse_stack(s):if stack_empty(s):print("栈为空,无元素可遍历!")returnprint("链栈元素(从栈顶到栈底):", end="")p = swhile p is not None:print(p.data, end=" ")p = p.nextprint()# 复制栈(将S复制到T)
def copy_stack(s):t = init_stack()if stack_empty(s):return t# 辅助栈用于临时存储元素(解决顺序问题)temp = init_stack()p = s# 先将S的元素逆序存入临时栈while p is not None:temp = push(temp, p.data)p = p.next# 再将临时栈的元素存入T,恢复原顺序while not stack_empty(temp):val, temp = pop(temp)t = push(t, val)return t# 判断两个栈是否相等(元素数量和对应位置元素都相同)
def stack_equal(s, t):# 长度不同则直接不相等if stack_length(s) != stack_length(t):return Falsep, q = s, twhile p is not None and q is not None:if p.data != q.data:return Falsep = p.nextq = q.nextreturn True# 逆置链栈(改变元素顺序)
def reverse_stack(s):if stack_empty(s) or stack_length(s) == 1:return s  # 空栈或只有一个元素无需逆置prev = Nonecurr = snext_node = None# 反转链表指针方向while curr is not None:next_node = curr.next  # 保存下一个节点curr.next = prev       # 反转当前节点指针prev = curr            # 移动prev到当前节点curr = next_node       # 移动curr到下一个节点return prev  # 返回新的栈顶指针# 测试函数
def main():import sys# 初始化栈s = init_stack()t = init_stack()print(f"初始化链栈S后,栈是否为空:{'是' if stack_empty(s) else '否'}")# 进栈操作print("\n执行进栈操作:依次入栈 10, 20, 30, 40, 50")s = push(s, 10)s = push(s, 20)s = push(s, 30)s = push(s, 40)s = push(s, 50)traverse_stack(s)print(f"栈S的长度:{stack_length(s)}")# 复制栈操作print("\n复制栈S到栈T...")t = copy_stack(s)print("栈T的元素:", end="")traverse_stack(t)print(f"栈S和栈T是否相等:{'是' if stack_equal(s, t) else '否'}")# 逆置栈操作print("\n逆置栈S...")s = reverse_stack(s)print("逆置后栈S的元素:", end="")traverse_stack(s)print(f"栈S和栈T是否相等:{'是' if stack_equal(s, t) else '否'}")# 再次逆置恢复原顺序s = reverse_stack(s)print("再次逆置后栈S的元素:", end="")traverse_stack(s)# 出栈和取栈顶操作print("\n执行出栈操作:")val, s = pop(s)print(f"出栈元素:{val}")val, s = pop(s)print(f"出栈元素:{val}")traverse_stack(s)print(f"当前栈顶元素:{get_top(s)}")print(f"当前栈S的长度:{stack_length(s)}")# 清空栈操作print("\n清空栈S...")s = clear_stack(s)print(f"清空后栈S是否为空:{'是' if stack_empty(s) else '否'}")print(f"清空后栈S的长度:{stack_length(s)}")# 测试栈Tprint("\n栈T的元素:", end="")traverse_stack(t)print(f"栈T的长度:{stack_length(t)}")# 销毁栈print("\n销毁链栈...")s = destroy_stack(s)t = destroy_stack(t)print(f"销毁后,栈S是否为空:{'是' if stack_empty(s) else '否'}")print(f"销毁后,栈T是否为空:{'是' if stack_empty(t) else '否'}")if __name__ == "__main__":main()
(三)Java代码
import java.util.Scanner;public class LinkStack {// 定义栈节点内部类private static class StackNode {int data;          // 数据域StackNode next;    // 指针域,指向后继节点// 节点构造函数public StackNode(int data) {this.data = data;this.next = null;}}private StackNode top;  // 栈顶指针// 链栈的初始化public LinkStack() {top = null;  // 栈顶指针置空,表示空栈}// 判断链栈是否为空public boolean stackEmpty() {return top == null;}// 求链栈的长度public int stackLength() {int length = 0;StackNode p = top;while (p != null) {length++;p = p.next;}return length;}// 链栈进栈操作public void push(int e) {StackNode p = new StackNode(e);  // 创建新节点p.next = top;                    // 新节点指向原栈顶top = p;                         // 更新栈顶指针为新节点}// 链栈出栈操作public int pop() {if (stackEmpty()) {System.err.println("错误:栈为空,无法执行出栈操作!");return -1;  // 栈空时返回特殊值}StackNode p = top;              // 暂存栈顶节点int e = p.data;                 // 获取栈顶元素值top = top.next;                 // 更新栈顶指针p.next = null;                  // 帮助垃圾回收return e;                       // 返回出栈元素}// 取链栈栈顶元素public int getTop() {if (stackEmpty()) {System.err.println("错误:栈为空,无栈顶元素!");return -1;  // 栈空时返回特殊值}return top.data;  // 返回栈顶元素值}// 清空链栈(保留栈结构,仅清空元素)public void clearStack() {top = null;  // 栈顶指针置空,Java垃圾回收会自动清理节点}// 销毁链栈(释放所有资源)public void destroyStack() {clearStack();  // 清空栈元素,Java无需额外操作}// 遍历链栈元素(从栈顶到栈底)public void traverseStack() {if (stackEmpty()) {System.out.println("栈为空,无元素可遍历!");return;}System.out.print("链栈元素(从栈顶到栈底):");StackNode p = top;while (p != null) {System.out.print(p.data + " ");p = p.next;}System.out.println();}// 复制栈(将当前栈复制到目标栈)public LinkStack copyStack() {LinkStack target = new LinkStack();if (stackEmpty()) {return target;}// 辅助栈用于临时存储元素(解决顺序问题)LinkStack temp = new LinkStack();StackNode p = top;// 先将当前栈的元素逆序存入临时栈while (p != null) {temp.push(p.data);p = p.next;}// 再将临时栈的元素存入目标栈,恢复原顺序while (!temp.stackEmpty()) {target.push(temp.pop());}return target;}// 判断两个栈是否相等(元素数量和对应位置元素都相同)public boolean stackEqual(LinkStack other) {// 长度不同则直接不相等if (this.stackLength() != other.stackLength()) {return false;}StackNode p = this.top;StackNode q = other.top;while (p != null && q != null) {if (p.data != q.data) {return false;}p = p.next;q = q.next;}return true;}// 逆置链栈(改变元素顺序)public void reverseStack() {if (stackEmpty() || stackLength() == 1) {return;  // 空栈或只有一个元素无需逆置}StackNode prev = null;StackNode curr = top;StackNode next = null;// 反转链表指针方向while (curr != null) {next = curr.next;  // 保存下一个节点curr.next = prev;  // 反转当前节点指针prev = curr;       // 移动prev到当前节点curr = next;       // 移动curr到下一个节点}top = prev;  // 更新栈顶指针}// 测试函数public static void main(String[] args) {LinkStack S = new LinkStack();LinkStack T = new LinkStack();// 初始化栈System.out.println("初始化链栈S后,栈是否为空:" + (S.stackEmpty() ? "是" : "否"));// 进栈操作System.out.println("\n执行进栈操作:依次入栈 10, 20, 30, 40, 50");S.push(10);S.push(20);S.push(30);S.push(40);S.push(50);S.traverseStack();System.out.println("栈S的长度:" + S.stackLength());// 复制栈操作System.out.println("\n复制栈S到栈T...");T = S.copyStack();System.out.print("栈T的元素:");T.traverseStack();System.out.println("栈S和栈T是否相等:" + (S.stackEqual(T) ? "是" : "否"));// 逆置栈操作System.out.println("\n逆置栈S...");S.reverseStack();System.out.print("逆置后栈S的元素:");S.traverseStack();System.out.println("栈S和栈T是否相等:" + (S.stackEqual(T) ? "是" : "否"));// 再次逆置恢复原顺序S.reverseStack();System.out.print("再次逆置后栈S的元素:");S.traverseStack();// 出栈和取栈顶操作System.out.println("\n执行出栈操作:");System.out.println("出栈元素:" + S.pop());System.out.println("出栈元素:" + S.pop());S.traverseStack();System.out.println("当前栈顶元素:" + S.getTop());System.out.println("当前栈S的长度:" + S.stackLength());// 清空栈操作System.out.println("\n清空栈S...");S.clearStack();System.out.println("清空后栈S是否为空:" + (S.stackEmpty() ? "是" : "否"));System.out.println("清空后栈S的长度:" + S.stackLength());// 测试栈TSystem.out.print("\n栈T的元素:");T.traverseStack();System.out.println("栈T的长度:" + T.stackLength());// 销毁栈System.out.println("\n销毁链栈...");S.destroyStack();T.destroyStack();System.out.println("销毁后,栈S是否为空:" + (S.stackEmpty() ? "是" : "否"));System.out.println("销毁后,栈T是否为空:" + (T.stackEmpty() ? "是" : "否"));}
}

四、程序运行结果展示

(一)C++程序运行截图

(二)Python程序运行截图

(三)Java程序运行截图

五、总结

链栈是一种基于链表实现的栈结构,具有先进后出(LIFO)的特性。其核心结构包括StackNode节点(含数据域和指针域)和栈顶指针LinkStack。主要操作包括初始化、判空、求长度、入栈、出栈、取栈顶元素等,时间复杂度多为O(1)。链栈的优势在于动态内存分配,无需预先确定容量,但需注意内存管理。此外,还支持高级操作如复制栈、判断栈相等、逆置栈等。本文提供了C++、Python和Java三种语言的完整实现代码及测试案例,展示了链栈的基本操作和运行结果。链栈适用于需要动态调整大小的场景,是数据结构中的重要实现方式。

http://www.dtcms.com/a/450080.html

相关文章:

  • 实战分享:股票数据API接口在量化分析中的应用与体验
  • 个人建设网站还要备案么wordpress建站详细教程视频
  • Vue2 和 Vue3 View
  • 乐趣做网站厦门做网站的公司
  • 使用jmeter做压力测试
  • [工作流节点15] 推送消息节点在企业内部通知中的应用实践
  • 热转印 东莞网站建设ui界面设计英文
  • 【数据结构学习篇】--树
  • Linux中驱动程序通过fasync异步通知应用程序的实现
  • MySQL索引优化:让查询快如闪电
  • 什么是营销型网站呢什么网站做新产品代理
  • 海沧建设网站多少jetpack报错 wordpress
  • 从零起步学习Redis || 第九章:缓存雪崩,缓存击穿,缓存穿透三大问题的成因及实战解决方案
  • 手机网站 微信链接网站建设工具
  • 网站建设年度总结客源通app下载
  • 欧美做暧网站jsp可以做网站吗
  • Variational Quantum Eigensolver笔记
  • 操作系统应用开发(二十四)RustDesk 404错误—东方仙盟筑基期
  • 网站菜单样式关于网站策划的文章
  • 做网站多久才会有收益网站打开显示站点目录
  • python异常
  • STM32CubeMonitor使用记录
  • 网站这么做海城seo网站排名优化推广
  • 做网站后的收获宁波seo软件免费课程
  • 网站设计精美案例常见软件开发模型有哪些
  • dedecms 网站还原数据之后 乱码网站开发用什么编程
  • 美发店会员管理软件培训
  • 建设部网站不支持360深圳市南山区住房和建设局网站官网
  • 电子签名法律实务全解析:从合规基础到风险防控的实战指南
  • 1元购网站建设广西壮族自治区市场监督管理局官网