【数据结构】栈(stack)-栈链(动态图解、c++、java)

文章目录

  • 栈链概述(图解)
  • 链栈的基本操作
    • 1.初始化
    • 2.入栈
    • 3.出栈
    • 4.取栈顶
  • 完整代码
  • 总结

GitHub同步更新(已分类):Data_Structure_And_Algorithm-Review

公众号:URLeisure 的复习仓库
公众号二维码见文末

以下是本篇文章正文内容,下面案例可供参考。


栈链概述(图解)

  • 栈可以用顺序存储,也可以用链式存储,分别称为顺序栈链栈
    【数据结构】栈(stack)-栈链(动态图解、c++、java)_第1张图片

  • 顺序栈是分配一段连续的空间,需要两个指针,base指向栈底,top指向栈顶。

  • 链栈每个节点的地址是不连续的,只需要一个栈顶指针即可。

  • 从图中可以看出,链栈的每个节点都包含两个域:数据域指针域

链栈的基本操作

  • 链栈是操作受限单链表
    • 只能在头部进行插入、删除、取值等操作;
    • 不能在中间和尾部操作进行任何操作。
  • 因此,可以按单链表的方法定义链栈的节点。

首先定义一个结构体(内部类),包含一个数据域和一个指针域。

c++代码如下(示例):

typedef struct SNode {
    int data;//数据域
    SNode *next;//指针域​
} *LinkStack;

java代码如下(示例):

public static class SNode {
    int data;
    SNode next;
}

1.初始化

  • 初始化一个空的链栈是不需要头结点的,因此只需要让栈顶指针为空即可。

c++代码如下(示例):

void Init(LinkStack &S) {
    S = NULL;
}

java代码如下(示例):

public static void init(SNode s){
    s = new SNode();
}

2.入栈

  • 入栈是将新元素节点压入栈顶。
  • 链栈中第一个节点为栈顶,因此将新元素插入到第一个节点的前面;
  • 然后修改栈顶指针指向新节点即可。

c++代码如下(示例):

void Push(LinkStack &S, int e){
    LinkStack p = new SNode;
    p->data = e;
    p->next = S;//新元素的下个地址是老的栈顶
    S = p;//栈顶上移
}

java代码如下(示例):

public static void push(int e) {
    SNode p = new SNode();
    p.data = e;
    p.next = s;
    s = p;
}
  1. 将新节点的指针域指向栈中最上面的指针​; p->next = s
  2. 讲新节点置为栈顶​。 ​s = p

【数据结构】栈(stack)-栈链(动态图解、c++、java)_第2张图片

3.出栈

  • 出栈是把栈顶元素删除。
  • 让栈顶指针指向下一个节点; s = s->next
  • 然后释放该节点空间(c++)。

c++代码如下(示例):

bool Pop(LinkStack &S, int &e){
    if(S == NULL){//栈空
        return false;
    }
    LinkStack p = S;//临时节点
    S = p->next;//栈顶下移
    e = p->data;//记录出栈元素
    delete p;//释放空间
    return true;
}

java代码如下(示例):

public static int pop() {
    if (s == null) {
        return -1;
    }
    SNode p = s;
    s = s.next;
    return p.data;
}

4.取栈顶

  • 取栈顶和出栈不同。
  • 取栈顶元素只是吧栈顶元素复制一份,栈顶指针未移动,栈内元素个数未变。

c++代码如下(示例):

int GetTop(LinkStack S){
    if(S == NULL){
        return -1;
    }
    return S->data;
}

java代码如下(示例):

public static int getTop() {
    if (s == null) {
        return -1;
    }
    return s.data;
}

完整代码

c++代码如下(示例):

#include

using namespace std;

typedef struct SNode {
    int data;
    SNode *next;
} *LinkStack;

void Init(LinkStack &S) {
    S = NULL;
}

void Push(LinkStack &S, int e) {
    LinkStack p = new SNode;
    p->data = e;
    p->next = S;
    S = p;
}

bool Pop(LinkStack &S, int &e) {
    if (S == NULL) {
        return false;
    }
    LinkStack p = S;
    S = p->next;
    e = p->data;
    delete p;
    return true;
}

int GetTop(LinkStack S) {
    if (S == NULL) {
        return -1;
    }
    return S->data;
}

int main() {
    LinkStack S;
    int n, e;
    Init(S);
    cout << "链栈初始化成功" << endl;
    cout << "输入元素个数:" << endl;
    cin >> n;
    cout << "输入元素,依次入栈" << endl;
    while (n--) {
        cin >> e;
        Push(S, e);
    }
    cout << "元素依次出栈!" << endl;
    while (S != NULL) {
        cout << GetTop(S) << " ";
        Pop(S, e);
    }
    cout << endl;
}

java代码如下(示例):

public class A {
    public static class SNode {
        int data;
        SNode next;
    }

    private static SNode s;

    public static void init(SNode s){
        s = new SNode();
    }

    public static void push(int e) {
        SNode p = new SNode();
        p.data = e;
        p.next = s;
        s = p;
    }

    public static int pop() {
        if (s == null) {
            return -1;
        }
        SNode p = s;
        s = s.next;
        return p.data;
    }

    public static int getTop() {
        if (s == null) {
            return -1;
        }
        return s.data;
    }

    public static void main(String[] args) {
        init(s);
        System.out.println("链栈初始化成功!");
        push(5);
        push(4);
        push(3);
        push(2);
        push(1);
        System.out.println("创建成功");
        System.out.println("元素依次出栈");
        while (s != null) {
            System.out.print(getTop() + " ");
            pop();
        }
        System.out.println();
    }
}

总结

  1. 顺序栈和链栈的基本操作都只需要常数时间,所以在时间效率 上难分伯仲。
  2. 空间效率 方面,顺序栈需要预先分配固定长度的空间,有可能造成空间的浪费或溢出。
  3. 链栈每次只分配一个节点,除非没有内存,否则不会出现溢出,但是每个节点需要一个指针域,结构性开销增加。
  • 因此,如果元素个数变化较大,可以采用链栈;反之,可以采用顺序栈。

在实际应用中,顺序栈比链栈应用更广泛。


关注公众号,感受不同的阅读体验

请添加图片描述

下期预告: 循环队列

你可能感兴趣的:(数据结构,c++,java,栈,图解法)