打印

数据结构之堆栈的C++语言实现

[复制链接]
1017|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
韩山童|  楼主 | 2017-1-5 16:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
上次用C语言四线堆栈,本次我们使用C++来实现堆栈,利用C++的模板机制,使堆栈可以存储任意的数据类型。同时,使用链表来模拟栈,使得栈的大小可以达到硬件所能支持的最大内存空间。好了,下面马上实现。
1。首先还是先定义栈中元素的数据类型:
/*堆栈使用链式存储,定义堆栈的节点数据类型*/
template <typename T>
struct Node
{
    T data;      //节点中的元素
    Node* next;

};


2.其次定义Stack类:
/*堆栈的类定义*/
template <typename T>
class Stack
{
private:
    Node<T>* mHead;      //头指针,用于管理链栈
    int mSize;           //栈中元素的个数
public:
    Stack();
    virtual ~Stack();

    void push(T e);     //入栈操作
    void pop(T& e);      //出栈操作
    bool isEmpty();     //判断栈空
    int getSize();      //返回栈中总元素

    void print();    //打印栈中的元素 但不出栈
};


3.下面就是实现Stack的各个函数:
(1)构造函数:
//构造函数 创建头指针
template <typename T>
Stack<T>::Stack()
{
    mHead = new Node<T>();  //创建头结点指针
    mHead->next = nullptr;      
    mSize = 0;                         //初始时栈中元素个数为0
}

(2)析构函数
/*析构函数:释放栈所占的堆内存*/
template <typename T>
Stack<T>::~Stack()
{
    Node<T>* p = mHead->next;  //p指向栈顶元素
    Node<T>* q = nullptr;           
    while (nullptr != p)  
    {
        q = p;
        p = p->next;
        delete q;  //逐一释放栈中元素
    }
    delete mHead;  //最后释放头指针
}

(3)入栈操作
//入栈:采用头插法创建
template <typename T>
void Stack<T>::push(T e)
{
    Node<T>* s = new Node<T>();
    s->data = e;
    s->next = mHead->next;
    mHead->next = s;
    ++mSize;
}

(4)出栈操作
//出栈
template <typename T>
void Stack<T>::pop(T& e)
{
    if(isEmpty())
    {
        printf("栈已空!!!\n");
        return;
    }
    Node<T>* p = mHead->next;
    mHead->next = p->next;
    e = p->data;
    delete p;
    --mSize;
}

(5)判断栈空
//判断栈空
template <typename T>
bool Stack<T>::isEmpty()
{
    return nullptr == mHead->next ? true : false;
}

(6)获取栈中元素个数
//获取栈中总元素个数
template <typename T>
int Stack<T>::getSize()
{
    return mSize;
}

(7)输出栈中元素,但不出栈
template <typename T>
void Stack<T>::print()
{
    Node<T>* p = mHead->next;
    while (nullptr != p)
    {
        cout << p->data << " ";
        p = p->next;
    }
}

4.测试
int main()
{
    Stack<int> st;
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);
    st.push(5);
    st.push(6);

    st.print();

    cout <<endl << "栈中元素个数:" << st.getSize() << endl;
    return 0;
}

输出:
6 5 4 3 2 1
栈中元素个数:6

相关帖子

沙发
韩山童|  楼主 | 2017-1-5 16:25 | 只看该作者
因为写帖子的时候太仓促,有错字的话麻烦各位大神指出来,蟹蟹!

使用特权

评论回复
板凳
韩山童|  楼主 | 2017-1-5 17:58 | 只看该作者
yyy71cj 发表于 2017-1-5 16:58
倒不是错别字的问题。
你这里使用了new,这对裸编程可能存在不便。不过作为非裸编程来说,倒没什么。
堆 ...

好的

使用特权

评论回复
地板
韩山童|  楼主 | 2017-1-5 18:00 | 只看该作者

用C++实现的话 我忍不住就想用new delete,而不是C语言的malloc和free了,也喜欢用链表

使用特权

评论回复
5
dongshan| | 2017-1-6 12:43 | 只看该作者
唉,C++中有stack,不需要自己写, 是stl的一部分,属于container adaptor.

使用特权

评论回复
6
michael_llh| | 2017-1-6 14:57 | 只看该作者
自己学习的话可以选择自己实现看看,但是实际用的话可以直接考虑用STL就可以

使用特权

评论回复
7
Simon21ic| | 2017-1-6 15:27 | 只看该作者
本帖最后由 Simon21ic 于 2017-1-6 15:31 编辑
yyy71cj 发表于 2017-1-5 16:58
倒不是错别字的问题。
你这里使用了new,这对裸编程可能存在不便。不过作为非裸编程来说,倒没什么。
堆 ...

裸编还不能用链表吗?这个我倒是不知道,链表非常常用的数据结构,适合需要动态添加删减的情况下。这个是和应用需求有关的,如果裸编里有类似应用需求,那我估计也是用诸如链表的实现方法吧?
链表和数组其实一样,可以通过当前元素,访问到下一个元素。
数组中,访问以下一个元素(或者上一个元素)的方法是通过当前元素的地址加上元素长度以及填充,而且,由于数组的这个特性,所以可以用索引来访问元素。
链表里,访问下一个元素(或者上一个元素)的方式是直接通过指针。

使用特权

评论回复
8
Simon21ic| | 2017-1-6 22:35 | 只看该作者
本帖最后由 Simon21ic 于 2017-1-7 00:17 编辑
yyy71cj 发表于 2017-1-6 21:30
这倒没有特别地规定。但是,链表非常耗费空间与速度。裸编程尽量让一切都在掌握之中,而不能有太多的不定 ...

裸编程只是没有操作系统,并不代表不能有动态分配
另外,动态分配并非不确定因素,比如可以使用内存池来实现动态分配,资源使用完全可控

我原来一直以为这些只是看应用需求,和平台没什么关系

使用特权

评论回复
9
Simon21ic| | 2017-1-7 09:27 | 只看该作者
yyy71cj 发表于 2017-1-7 08:14
若是完全可控,自然可以动态分配了,这需要有足够的修为……

即使是真正的动态分配,也是可控的,比如设置一个可以动态分配的最大内存
当然,当然这种情况下,最大的风险反而是其他代码有BUG,内存溢出,覆盖了MCB

使用特权

评论回复
10
batsong| | 2017-1-7 14:12 | 只看该作者
只有允许死机的设备才能使用new和malloc,这不是我说的,这是arm编译器的手册说的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

43

帖子

1

粉丝