栈的概念、实现以及应用

来源:互联网 发布:美国数据库 编辑:程序博客网 时间:2024/05/17 22:54

概念

  • 栈是限定仅在表尾进行插入或删除操作的线性表。
  • 对栈来说,表尾称为栈顶,表头称为栈底,不含元素的空表称为空栈。
  • 栈的修改是按照后进先出的原则进行的,也称为LIFO

基本操作

  • InitStack(),构造一个空栈
  • ClearStack(),将栈清空
  • isEmpty(),判断栈是否为空,是返回true,否则返回false
  • StackLength(),返回栈的长度
  • Top(&elem),返回栈顶元素
  • Push(&elem),向栈顶添加元素
  • Pop(),删除栈顶元素
  • Traverse(),遍历元素一遍

实现(顺序表和链接表)

  • 顺序表
#define STACK_INIT_SIZE 5#define INCREMENT 2template<typename T>class myStack{public:    myStack();    ~myStack();    void ClearStack();    bool isEmpty();    int StackSize();    T Top();    void Push(T elem);    T Pop();    void StackTraverse(void (*visit)(T));private:    T* base;    T* top;    int count;    int stackSize;};template<typename T>myStack<T>::myStack(){    base = new T[STACK_INIT_SIZE];    top = base;    count = 0;    stackSize = STACK_INIT_SIZE;}template<typename T>myStack<T>::~myStack(){    delete[] base;}template<typename T>void myStack<T>::ClearStack(){    delete[] base;    base = new T[STACK_INIT_SIZE];    top = base;    count = 0;}template<typename T>bool myStack<T>::isEmpty(){    if (count == 0 && top == base)        return true;    else        return false;}template<typename T>int myStack<T>::StackSize(){    return count;}template<typename T>T myStack<T>::Top(){    return *(top-1);}template<typename T>void myStack<T>::Push(T elem){    //stack is full    if (count == stackSize)    {        T* newBase = new T[stackSize + INCREMENT];        //copy        for (int i = 0; i < count; i++)        {            newBase[i] = base[i];        }        top = &(newBase[stackSize]);        //push        *top = elem;        top++;        count++;        //delete        delete[]base;        base = newBase;        stackSize += INCREMENT;    }    else    {        *top = elem;        top++;        count++;    }}template<typename T>T myStack<T>::Pop(){    count--;    top--;    return *top;}template<typename T>void myStack<T>::StackTraverse(void(*visit)(T)){    for (int i = count - 1; i >= 0; i--)    {        visit(base[i]);    }}
  • 链接表,宏与上面文件共用
template<class T>struct Node{    T elem;    Node* next;    Node()    {        next = NULL;    }};template<class T>class myStack2{public:    myStack2();    ~myStack2();    void ClearStack();    bool isEmpty();    int StackSize();    T Top();    void Push(T elem);    T Pop();    void StackTraverse(void(*visit)(T));private:    Node<T>* top;    int count;};template<class T>myStack2<T>::myStack2(){    top = NULL;}template<class T>myStack2<T>::~myStack2(){    Node<T>* tmp = NULL;    while (top != NULL)    {        tmp = top;        top = top->next;        delete tmp;    }}template<class T>void myStack2<T>::ClearStack(){    Node<T>* tmp = NULL;    while (top != NULL)    {        tmp = top;        top = top->next;        delete tmp;    }    count = 0;}template<class T>bool myStack2<T>::isEmpty(){    return top == NULL;}template<class T>int myStack2<T>::StackSize(){    return count;}template<class T>T myStack2<T>::Top(){    return top->elem;}template<class T>void myStack2<T>::Push(T elem){    Node<T>* tmp = top;    top = new Node<T>;    top->elem = elem;    top->next = tmp;     count++;}template<class T>T myStack2<T>::Pop(){    T ret;    if (top != NULL)    {        Node<T>* tmp = top;        ret = tmp->elem;        top = top->next;        delete tmp;        count--;    }    return ret;}template<class T>void myStack2<T>::StackTraverse(void(*visit)(T)){    Node<T>* cur = top;    while (cur != NULL)    {        visit(cur->elem);        cur = cur->next;    }}

ps:写代码时候遇到的问题

  • 用template模板写类的时候需要把类的h文件和cpp文件写在一起,否则会报链接错误
  • 顺序表实现要难一点,因为地址是已经分好了,所以不能用判断top和NULL是否相等来判断是否空栈,所以需要top指针指向下一个push进来的,如空栈top指向分配的第一个地址,取top和pop的时候需要返回的是top-1的地址指向的元素,与链表很直观的理解不同。
  • 自己的问题:模板的格式和传递函数的写法有点生疏,算是复习了一遍。

栈的应用

  • 数制转换:将10进制数x转成n进制,只需不断让x%n的值push进栈,再让x/=x,直到x为0,然后顺序把栈中元素pop出并顺序输出即可完成进制转换。
  • 括号匹配:遇到左括号push进去,遇到右括号判断栈顶元素是否对应的左括号,是则pop出,否则括号不匹配。
  • 行编辑软件:设立一个输入缓冲区,接受用户输入的一行字符,然后逐行存入用户数据区。用户发现输入一个错误字符的时候可以用一个退格符“#”表示前一个字符无效,“@”表示之前的字符无效。栈实现:每遇到一个输入就push进去,遇到“#”就pop,遇到“@”就clear。
0 0
原创粉丝点击