四时宝库

程序员的知识宝库

数据结构-栈-手打代码(educoder数据结构栈)

前言

  • 数据结构是计算机学科的基础,而类链表结构又是数据结构最基本的结构,包括List、stack、queue等;
  • 然而,大部分同学甚至连一个可用的List都写不出来;
  • 故,下面手打了一份栈实现,供参考;

注意点

  • 逻辑正确; 这个也是最基本的
  • 模板正确使用;
  • 内存的正确申请与释放
  • 参数与返回值类型的正确使用
  • 高效

代码

#include <iostream>
#include <assert.h>

using namespace std;

// 栈是一种基本数据结构,特色是后进先出

// 模板使用方式
template <typename T>
class MyStack
{
    // 节点定义 这个可以定义在MyStack内部,因为不需要在外部调用
    struct Node
    {
        T value_;           // 存储数据的地方
        struct Node *up_;   // 后置节点指针
        struct Node *down_; // 前置节点指针
        Node(const T &value, Node *down = nullptr, Node *up = nullptr) : value_(value), down_(down), up_(up)
        {
        }
    };

private:
    // 这里使用了顶指针,因为都只是头部操作,所以就不需要底部指针了。
    Node *top_;
    // Node *bottom_;

    int32_t size_;

public:
    MyStack() : top_(nullptr), size_(0) {}

    // 拷贝构造 注意参数需要是引用,否则多一次拷贝
    MyStack(const MyStack<T> &other) : top_(nullptr), size_(0)
    {

        Node *cur = other.top_;
        Node *bottom = top_;
        while (cur)
        {
            Node *temp = new Node(cur->value_, nullptr, bottom);
            // 注释的代码是处理temp的上下指针, 因为通过Node new的时候传入了,所以注释掉
            // temp->down_ = nullptr;
            // temp->up_ = bottom;

            // 如果存在底部指针,底部的向下指针指向temp
            if (bottom)
            {
                bottom->down_ = temp;
            }
            // 如果top_不存在,这里设置一下
            if (!top_)
            {
                top_ = temp;
            }
            // 更新当前的底部指针
            bottom = temp;

            // 向下移动cur
            cur = cur->down_;

            //
            size_++;
        }
    }
    // 注意参数需要为const引用传入,不加const的话会无法传入const类型,不加引用会多一次对象拷贝
    void push(const T &value)
    {
        Node *temp = new Node(value, top_, nullptr);
        // 注释的代码是处理temp的上下指针, 因为通过Node new的时候传入了,所以注释掉
        // temp->down_ = top_;
        // temp->up_ = nullptr;

        // 如果top_存在,top_的向上指针指向temp
        if (top_)
        {
            top_->up_ = temp;
        }
        // 更新top_指针
        top_ = temp;

        //cout<<temp->down_<<" "<<temp->up_<<endl;
        size_++;
    }

    T pop()
    {
        assert(top_);
        // 因为返回的数值所在节点需要delete,所以只能通过值传递回去
        T ret = top_->value_;

        // 标记需要delete的节点指针,用于在下面delete,这里特别容易忘记
        auto to_delete = top_;

        // 移动top_指针
        top_ = top_->down_;
        if (top_)
        {
            // top_的向上指针置空
            top_->up_ = nullptr;
        }
        size_--;

        // 删除节点
        delete to_delete;
        return ret;
    }

    void reverse()
    {
        // 反转的话,先把top_另存,然后自上而下取节点,加在现在链顶部

        // 缓存并移除
        auto cur = top_;
        top_ = nullptr;

        while (cur)
        {
            // cur为待取节点指针
            // next为下一个节点指针
            auto next = cur->down_;
            // 处理取出的节点指针
            cur->up_ = nullptr;
            cur->down_ = nullptr;

            if (!top_)
            {
                // 如果top不存在,设置top为取出的节点指针
                top_ = cur;
            }
            else
            {
                // top_和cur互指
                top_->up_ = cur;
                cur->down_ = top_;
                // 移动top_指针
                top_ = cur;
            }
            // 移动待取指针
            cur = next;
        }
    }
    int32_t size()
    {
        return size_;
    }
};

int main()
{
    MyStack<int> test_stack;
    for (int32_t i = 0; i < 3; i++)
        test_stack.push(i);

    test_stack.reverse();
    while (test_stack.size())
    {
        cout << test_stack.pop() << endl;
    }

    for (int32_t i = 0; i < 3; i++)
        test_stack.push(i);

    MyStack<int> test_stack1 = test_stack;

    test_stack1.reverse();
    while (test_stack1.size())
    {
        cout << test_stack1.pop() << endl;
    }
}

后记

  • 希望本篇能有所帮助;如果有其他数据结构不明,也可以留言区骚扰;

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接