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

目录

一、链栈基础结构

二、核心操作算法详解

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的元素逆序存入temp
    while (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;        // 移动prev
        curr = 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;

    // 测试栈T
    cout << "\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 = 0
    p = s
    while p is not None:
        length += 1
        p = p.next
    return 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 None
    return 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("栈为空,无元素可遍历!")
        return
    print("链栈元素(从栈顶到栈底):", end="")
    p = s
    while p is not None:
        print(p.data, end=" ")
        p = p.next
    print()


# 复制栈(将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 False
    
    p, q = s, t
    while p is not None and q is not None:
        if p.data != q.data:
            return False
        p = p.next
        q = q.next
    
    return True


# 逆置链栈(改变元素顺序)
def reverse_stack(s):
    if stack_empty(s) or stack_length(s) == 1:
        return s  # 空栈或只有一个元素无需逆置
    
    prev = None
    curr = s
    next_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)}")
    
    # 测试栈T
    print("\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());

        // 测试栈T
        System.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三种语言的完整实现代码及测试案例,展示了链栈的基本操作和运行结果。链栈适用于需要动态调整大小的场景,是数据结构中的重要实现方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值