数据结构--栈--顺序栈/链式栈(附: 字符括号合法配对检测)

栈结构:先进后出,后进先出,像叠盘子一样,先叠的后用。
代码github地址 https://github.com/hitskyer/course/tree/master/dataAlgorithm/chenmingming/stack

1.顺序栈(数组存储,需给定数组大小,到达容量需要copy转移数据)

1.1 头文件 arrStack.h

//
// Created by mingm on 2019/3/27.
//
#ifndef STACK_ARRSTACK_H
#define STACK_ARRSTACK_H
typedef unsigned int UINT;
template <class T>
class arrStack
{
public:
    arrStack(int capacity);       // 初始化栈
    ~arrStack(void);      // 析构栈

    bool Empty() const;       // 判断是否为空
    bool IsFull() const;    //判断栈是否满了
    void Clear();     // 则清空栈

    T& GetTop() const; // 得到栈顶元素
    UINT GetLength() const;    // 返回栈的长度

    void Push(T &data);    //往栈中压入数据
    void Expand();  //栈扩容
    void Pop();       //将栈顶数据弹出
    void print();   //自己加的接口,打印输出stack内容
private:
    int m_pTop;    // 栈顶指针
    UINT m_nStackLen;  // 栈容量
    T* arr; //数组arr
};

#endif //STACK_ARRSTACK_H

1.2 类实现文件 arrStack.cpp

//
// Created by mingm on 2019/3/27.
//
#include "arrStack.h"
#include <iostream>
using namespace std;
template <class T> arrStack<T>::arrStack(int capacity):m_pTop(-1),m_nStackLen(capacity)
{
    arr = new T[capacity];
}
template <class T> arrStack<T>::~arrStack()
{
    Clear();
    delete [] arr;
    arr = NULL;
}
template <class T> bool arrStack<T>::Empty() const
{
    return m_pTop == -1;
}
template <class T> bool arrStack<T>::IsFull() const
{
    return m_pTop == m_nStackLen - 1;
}
template <class T> void arrStack<T>::Clear()
{
    m_pTop = -1;
}
template <class T> void arrStack<T>::Push(T &data)
{
    if(IsFull())
    {
// cout << "overflow !" << endl;
        Expand();
    }
    arr[++m_pTop] = data;
}
template <class T> void arrStack<T>::Expand()
{
    m_nStackLen = 2 * m_nStackLen;
    T* temparr = new T[m_nStackLen];
    for(int i = 0; i <= m_pTop; ++i)
    {
        temparr[i] = arr[i];
    }
    T* temp = arr;
    arr = temparr;
    temparr = temp;
    delete [] temparr;
    temparr = NULL;
}
template <class T> void arrStack<T>::Pop()
{
    if(!Empty())
        --m_pTop;
}
template <class T> T& arrStack<T>::GetTop() const
{
    if(!Empty())
        return arr[m_pTop];
    throw "no elem!";   //抛出异常
}
template <class T> UINT arrStack<T>::GetLength() const
{
    return m_nStackLen;
}
template <class T> void arrStack<T>::print()
{
    cout << "----arrstack top----" << endl;
    int i = m_pTop, j = m_pTop;
    while(m_pTop != -1 && j >= 0)
    {
        cout << "No." << i-- << " elem " << arr[j--] << endl;
    }
    cout << "----arrstack bottom----" << endl;
}

1.3 测试程序及括号格式合法性检测 arrstack_testMain.cpp(练习了下try,catch)

//
// Created by mingm on 2019/3/27.
//
#include "arrStack.cpp"
#include <string>
#include <iostream>
using namespace std;
int main()
{
    for(int i = 0; i < 20; ++i)
    {
        int k = 0;
        arrStack<int> int_arr_stack(8);
        int_arr_stack.print();
        cout << "the capacity of stack is " << int_arr_stack.GetLength() << endl;
        while(k < i)
        {
            int_arr_stack.Push(k);
            ++k;
        }
        try
        {
            cout << "top elem is " << int_arr_stack.GetTop() << endl;
        }
        catch(const char* str)
        {
            cout << str << endl;
        }
        cout << "the capacity of stack is " << int_arr_stack.GetLength() << endl;
        int_arr_stack.print();
        int_arr_stack.Clear();
        cout << "---------------------------------" << endl;
    }
    cout << "以下测试一个字符串是否有非法格式的括号" << endl;
    char conti = 'y', str;
    while(conti == 'y'|| conti == 'Y')
    {
        bool legal = true;
        arrStack<char> charstack(100);
        cout << "please enter a string to check its brackets legal or not !" << endl;
        while(cin.get(str) && str != '\n')  //不断地获取输入的字符
        {
            if(str == '{' || str == '[' || str == '(')  //遇到左括号不断地压栈
            {
                charstack.Push(str);
                continue;
            }
            switch(str) //遇到非左括号
            {
                case '}':
                    try
                    {
                        if(charstack.GetTop()  && charstack.GetTop() == '{')   //栈不为空且栈顶与右括号匹配
                            charstack.Pop();    //删除左括号
                        else
                            legal = false;  //直接遇上右括号,非法;or 栈顶与当前右括号不匹配
                    }
                    catch(const char* str)  //若捕获try内的异常,没有元素在栈内,则遇到右括号,非法
                    {
                        legal = false;
                    }
                    break;
                case ']':
                    try
                    {
                        if(charstack.GetTop() && charstack.GetTop() == '[')
                            charstack.Pop();
                        else
                            legal = false;
                    }
                    catch(const char* str)
                    {
                        legal = false;
                    }
                    break;
                case ')':
                    try
                    {
                        if(charstack.GetTop() && charstack.GetTop() == '(')
                            charstack.Pop();
                        else
                            legal = false;
                    }
                    catch(const char* str)
                    {
                        legal = false;
                    }
                    break;
                default:
                    break;
            }
            if(!legal)
                break;  //如果非法,不必循环了,直接退出
        }
        if(legal && charstack.Empty())  //如果合法,且符号都匹配了(栈为空)
            cout << "legal string !" << endl;
        else
        {
            cout << "illegal string !" << endl;
            cin.ignore(10000,'\n'); //清除非法字符后面尚未get的字符
        }
        cout << "continue? y/n: " ;
        cin >> conti;
        cin.get();
    }
    return 0;
}

2.链式栈(链表存储,无需给定长度)

2.1 头文件 stack.h

/* * 概述: 栈 * 作者: dongyaxing * 版本: 1.0 * 创建时间:2019/3/25 20:47 * 修改者: liuyanfu * 修改时间: 2019/3/25 21:14 */
#ifndef _STACK_H
#define _STACK_H
template <class T>
struct SNode
{
    T data;
    SNode *pNext;
};
template <class T>
        using StackNode = SNode<T>* ;	//某些编译器不支持改语法
//template <class T> typedef SNode<T>* StackNode; //错误写法
typedef unsigned int UINT;
template <class T>
class Stack
{
public:
    Stack(void);      // 初始化栈
    ~Stack(void);     // 析构栈

    bool Empty() const;       // 判断是否为空
    void Clear();     // 则清空栈

    StackNode<T> GetTop() const;   // 得到栈顶元素
    UINT GetLength() const;    // 返回栈的长度

    void Push(T &data);    //往栈中压入数据
    void Pop();       //将栈顶数据弹出
    void print();   //自己加的接口,打印输出stack内容
private:
    StackNode<T> m_pTop;   // 栈顶元素
    UINT m_nStackLen;  // 栈长度
};

#endif //_STACK_H

2.2 类实现文件 stack.cpp

//
// Created by mingm on 2019/3/26.
//
#include "stack.h"
#include <iostream>
using namespace std;
template <class T> Stack<T>::Stack():m_pTop(NULL),m_nStackLen(0){}
template <class T> Stack<T>::~Stack() {   Clear();    }
template <class T> bool Stack<T>::Empty() const
{
    return m_nStackLen == 0;
}
template <class T> void Stack<T>::Clear()
{
    while(m_pTop != NULL)
    {
        Pop();
    }
}
template <class T> void Stack<T>::Push(T &data)
{
    StackNode<T> newNode = new SNode<T>;
    newNode->data = data;
    newNode->pNext = NULL;
    if(m_pTop == NULL)
    {
        m_pTop = newNode;
    }
    else
    {
        newNode->pNext = m_pTop;
        m_pTop = newNode;
    }
    m_nStackLen++;
}
template <class T> void Stack<T>::Pop()
{
    if(m_pTop != NULL)
    {
        StackNode<T> temp = m_pTop->pNext;
        delete m_pTop;
        m_pTop = temp;
        m_nStackLen--;
    }
}
template <class T> StackNode<T> Stack<T>::GetTop() const
{
    return m_pTop;
}
template <class T> UINT Stack<T>::GetLength() const
{
    return m_nStackLen;
}
template <class T> void Stack<T>::print()
{
    cout << "----stack top----" << endl;
    StackNode<T> temp = m_pTop;
    size_t i = 0;
    while(temp != NULL)
    {
        cout << "No." << ++i << " elem " << temp->data << endl;
        temp = temp->pNext;
    }
    cout << "----stack bottom----" << endl;
}

2.3 链式栈 测试主程序

#include "stack.cpp"
#include <string>
#include <iostream>

using namespace std;
int main()
{
    for(int i = 0; i < 10; ++i)
    {
        int nums = 0;
        Stack<int> intstack;
        if(intstack.Empty())
            cout << "intstack is empty!" << endl;
        cout << "after push nums: " << endl;
        while(nums < i)
        {
            intstack.Push(nums);
            nums++;
        }
        intstack.print();
        intstack.Pop();
        cout << "len of stack is " << intstack.GetLength() << endl;
        if(intstack.GetTop())
            cout << "top elem is " << intstack.GetTop()->data << endl;
        if(!intstack.Empty())
            cout << "intstack is not empty!" << endl;
        intstack.print();
        cout << "---------------------------------" << endl;
    }
    cout << "以下测试一个字符串是否有非法格式的括号" << endl;
    char conti = 'y', str;
    while(conti == 'y'|| conti == 'Y')
    {
        bool legal = true;
        Stack<char> charstack;
        cout << "please enter a string to check its brackets legal or not !" << endl;
        while(cin.get(str) && str != '\n')  //不断地获取输入的字符
        {
            if(str == '{' || str == '[' || str == '(')  //遇到左括号不断地压栈
            {
                charstack.Push(str);
                continue;
            }
            switch(str) //遇到非左括号
            {
                case '}':
                    if(charstack.GetTop() && charstack.GetTop()->data == '{')   //栈不为空且栈顶与右括号匹配
                        charstack.Pop();    //删除左括号
                    else
                        legal = false;  //直接遇上右括号,非法;or 栈顶与当前右括号不匹配
                    break;
                case ']':
                    if(charstack.GetTop() && charstack.GetTop()->data == '[')
                        charstack.Pop();
                    else
                        legal = false;
                    break;
                case ')':
                    if(charstack.GetTop() && charstack.GetTop()->data == '(')
                        charstack.Pop();
                    else
                        legal = false;
                    break;
                default:
                    break;
            }
            if(!legal)
                break;  //如果非法,不必循环了,直接退出
        }
        if(legal && charstack.Empty())  //如果合法,且符号都匹配了(栈为空)
            cout << "legal string !" << endl;
        else
        {
            cout << "illegal string !" << endl;
            cin.ignore(10000,'\n'); //清除非法字符后面尚未get的字符
        }
        cout << "continue? y/n: " ;
        cin >> conti;
        cin.get();
    }
    return 0;
}

3.valgrind测试正确

《数据结构--栈--顺序栈/链式栈(附: 字符括号合法配对检测)》

点赞