1. 程式人生 > >四、棧

四、棧

前言

應用:瀏覽器的前進、後退功能

一、棧的概述

棧(stack)是限定僅在表尾(棧頂)進行插入和刪除操作的線性表。
棧頂(top):允許插入和刪除的一端,另一端成為棧底(bottom)

後進先出(Last In First Out,LIFO),先進後出
==》只允許在一端插入和刪除資料。

棧主要包含兩個操作:進棧和出棧 ,也就是在棧頂插入一個數據和從棧頂刪除一個數據。
其中,入棧也稱壓棧、入棧;出棧也稱彈棧。
在這裡插入圖片描述

二、C++棧的方法

  1. push()——向棧內壓入一個成員;
  2. pop()——從棧頂彈出一個成員;
  3. empty()
    ——如果棧為空返回true,否則返回false;
  4. top()——返回棧頂,但不刪除成員;
  5. size()——返回棧內元素的大小;
#include<iostream>
#include<stack>
using namespace std;

int main()
{	
	stack <int>stk;
	//入棧
	for(int i = 0; i < 50; i++)
	{
		stk.push(i);
	}
	cout<<"棧的大小:"<<stk.size()<<endl;
	while(!stk.
empty()) { cout<<stk.top()<<endl; stk.pop(); } cout<<"棧的大小:"<<stk.size()<<endl; return 0; }

三、造輪子

棧可以用陣列來實現,也可以用連結串列來實現

1、基於陣列的實現

用到c++中的模板類(template)

#include <iostream>
#include <stdlib.h>
using namespace std;

#define MAXSIZE 0xffff

// 類模板宣告的寫法
// template <class T> class 類名{}; template<class type> class my_stack { int top; type* my_s; int maxsize; public: // 建構函式,建立預設大小的棧 my_stack():top(-1),maxsize(MAXSIZE) { my_s = new type[maxsize]; if(my_s==NULL) { // 輸出到標準錯誤的ostream物件,常用於程式錯誤資訊; // 預設情況下被關聯到標準輸出流,但它不被緩衝, // 也就說錯誤訊息可以直接傳送到顯示器,而無需等到緩衝區或者新的換行符時,才被顯示 cerr<<"動態儲存分配失敗!"<<endl; exit(1); } } // 建構函式,建立指定大小的棧 my_stack(int size):top(-1),maxsize(size) { my_s = new type[size]; if(my_s == NULL) { cerr<<"動態儲存分配失敗!"<<endl; exit(1); } } // 解構函式 ~my_stack() { delete[] my_s; } // 判斷棧是否為空 bool Empty(); // 壓棧 void Push(type tp); // 返回棧頂元素 type Top(); // 出棧 void Pop(); // 棧的大小 int Size(); }; template<class type> bool my_stack<type>::Empty() { if(top == -1) return true; else return false; } template<class type> void my_stack<type>::Push(type tp) { if(top+1 < maxsize) { my_s[++top]=tp; } else { cout<<"滿棧"<<endl; exit(1); } } template<class type> type my_stack<type>::Top() { if(top != -1) return my_s[top]; else { cout<<"空棧"<<endl; exit(1); } } template<class type> void my_stack<type>::Pop() { if(top >= 0) { top--; } else { cout<<"空棧"<<endl; exit(1); } } template<class type> int my_stack<type>::Size() { return top+1; } // 對比測試程式 int main(int argc, char *argv[]) { my_stack<int> stk; for(int i=0; i<50; i++) { stk.Push(i); } cout<<"棧的大小:"<<sizeof(stk)<<endl; w/hile(!stk.Empty()) { cout<<stk.Top()<<endl; stk.Pop(); } cout<<"棧的大小:"<<sizeof(stk)<<endl; return 0; }

2、基於連結串列的實現

用到c++中的模板類(template)

#include <iostream>
using namespace std;

template<class T> class LinkedListStack
{
public:
    LinkedListStack();
    ~LinkedListStack();
    
    // 入棧
    void Push(const T & data);
    // 只返回棧頂元素,但不刪除棧頂元素
    T Top();
    // 出棧
    T Pop();
    // 返回棧的大小
    int size() const;

private:
    // 存放棧的大小,因為單鏈表所以這裡不規定棧的最大可承載量
    int count;
    struct LinkedNode
    {
        T data;
        LinkedNode * next;
    };
    LinkedNode * head;  //單鏈表的頭指標,不帶頭結點
};

// 建構函式
template<class T> LinkedListStack<T>::LinkedListStack()
{
    this->count = 0;
    this->head = new LinkedNode;
    this->head->next = NULL;
}

// 解構函式,清空棧
template<class T> LinkedListStack<T>::~LinkedListStack()
{
    LinkedNode *ptr, *temp;
    ptr = head;
    while (ptr->next != NULL) {
        temp = ptr->next;
        ptr->next = temp->next;
        delete temp;
    }
    delete head;//刪除頭結點
    this->head = NULL;
    this->count = 0;
}


// 入棧
template<class T> void LinkedListStack<T>::Push(const T &data)
{
    LinkedNode * insertPtr = new LinkedNode;
    insertPtr->data = data;
    insertPtr->next = this->head->next;
    head->next = insertPtr;
    this->count++;
    cout<<"Push data:"<<this->head->next->data<<endl;
}
// 返回棧頂元素,即出棧,但不刪除棧頂元素
template<class T> T LinkedListStack<T>::Top()
{
    if(this->count == 0 || this->head->next == NULL)
    {
        cout<<"Stack is empty, Top fail"<<endl;
        return NULL;
    }
    else {
        LinkedNode * temp = this->head->next;
        T data = temp->data;
        return data;
    }
}
// 出棧
template<class T> T LinkedListStack<T>::Pop()
{
    if(this->count == 0 || this->head->next == NULL)
    {
        cout<<"stack is empty, Pop is fail"<<endl;
        return NULL;
    }
    else {
        LinkedNode * temp = this->head->next;
        this->head->next = temp->next;
        T data = temp->data;
        delete temp;
        this->count--;
        return data;
    }
}
// 返回棧的大小
template<class T> int LinkedListStack<T>::size() const
{
    return this->count;
}


int main(int argc, char *argv[])
{
    cout << " === StackBasedOnLinkedList test begin ===" << endl;
    LinkedListStack <float> stack;
    cout << "size==="<<stack.size()<<endl;
    stack.Push(10.1);
    stack.Push(20.2);
    stack.Push(30.);
    stack.Push(40.4);
    stack.Push(50.5);
    stack.Push(60.6);
    cout << "size==="<<stack.size()<<endl;
    cout << "stack Top  " << stack.Top() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "size==="<<stack.size()<<endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "size==="<<stack.size()<<endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Top  " << stack.Top() << endl;
    stack.Push(110.1);
    stack.Push(120.2);
    stack.Push(130.3);
    stack.Push(140.4);
    stack.Push(150.5);
    stack.Push(160.6);
    cout << "size==="<<stack.size()<<endl;
    cout << "stack Top  " << stack.Top() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Top  " << stack.Top() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    cout << "size==="<<stack.size()<<endl;
    cout << "stack Top  " << stack.Top() << endl;
    cout << "stack Pop  " << stack.Pop() << endl;
    system("pause");
    return 0;
}