資料結構筆記之用C++實現順序棧和鏈式棧
阿新 • • 發佈:2018-12-31
這裡介紹兩種實現棧的方式:“順序棧”和“鏈式棧”,各有各的優缺點。
不管是“順序棧”還是“鏈式棧”,我們可以先定義一個棧的ADT(抽象資料型別),如下面的“stack.h”
#ifndef STACK_H
#define STACK_H
const int maxSize=50;
template <class T>
class Stack{
public:
Stack(){};
virtual void Push(const T& x)=0;
virtual bool Pop(T& x)=0;
virtual bool getTop(T& x)const =0;
virtual bool isEmpty()const=0;
virtual bool isFull()const=0;
virtual int getSize() const=0;
};
#endif
關於模版類“template”的使用可以參考網上的教程,這裡定義了棧的幾個基本操作:構造棧,進棧,退棧,獲取棧頂元素,判斷棧空,判斷棧滿,獲取棧的元素個數
1、“順序棧”的實現
建立“seqstack.h”,並在裡面實現順序棧
/*
** 順序棧的模板類及其成員函式的實現,建立“seqstack.h”
*/
#ifndef SEQSTACK_H
#define SEQSTACK_H
#include <assert.h>
#include <iostream>
#include "stack.h"
using namespace std;
const int stackIncreament=20;
template <class T>
class SeqStack :public Stack<T>{
public:
/*
** 建立一個空棧
*/
SeqStack(int sz=50);
/*
** 解構函式
*/
~SeqStack(){delete[]elements;}
/*
** 進棧
*/
void Push(const T& x);
/*
** 退棧
*/
bool Pop(T& x);
/*
** 獲取棧頂元素
*/
bool getTop(T& x)const;
/*
** 判斷棧是否為空
*/
bool isEmpty()const {return(top == -1)?true:false;}
/*
** 判斷棧是否為滿
*/
bool isFull()const {return(top == maxSize-1)?true:false;}
/*
** 獲取棧的元素個數
*/
int getSize()const {return top+1;}
/*
** 清空棧
*/
void MakeEmpty(){top=-1;}
/*
** 輸出棧中元素的過載操作<<
*/
friend ostream& operator << (ostream& os,SeqStack<T>& s);
private:
/*
** 存放棧中元素的棧陣列
*/
T* elements;
/*
** 棧頂元素
*/
int top;
/*
** 棧最大可容納的元素個數
*/
int maxSize;
/*
** 棧溢位的處理
*/
void overflowProcess();
};
//由於編譯器的關係,模板類成員函式必須和申明在一個同一個“.h”檔案裡
template<class T>
SeqStack<T>::SeqStack(int sz/* =50 */):top(-1),maxSize(sz){
elements=new T[maxSize];
assert(elements!=NULL);
};
template<class T>
void SeqStack<T>::overflowProcess(){
T * newArray = new T[maxSize+stackIncreament];
if (newArray==NULL){cerr<<"add stack area failed!"<<endl;exit(1);}
for (int i=0;i<=top;i++)
{
newArray[i]=elements[i];
}
maxSize=maxSize+stackIncreament;
delete[]elements;
elements=newArray;
};
template<class T>
void SeqStack<T>::Push(const T& x){
if (isFull()==true)
{
overflowProcess();
}
elements[++top]=x;
};
template<class T>
bool SeqStack<T>::Pop(T& x)
{
if (isEmpty()==true)
{
return false;
}
x=elements[top--];
return true;
};
template<class T>
bool SeqStack<T>::getTop(T& x)const
{
if (isEmpty()==true)
{
return false;
}
x=elements[top];
return true;
};
template<class T>
ostream& operator<<(ostream& os,SeqStack<T>& s){
os<<"top=="<<s.top<<endl;
for (int i=0;i<=s.top;i++)
{
os<<i<<":"<<s.elements[i]<<endl;
}
return os;
};
#endif
2、“鏈式棧”的實現
首先先定義一個結點結構體“LinkedList.h”
/*
** 單鏈表結點的結構體定義
*/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
template <class T>
struct LinkNode{
/*
** 資料域
*/
T data;
/*
** 鏈指標域
*/
LinkNode<T> *link;
/*
** 僅初始化指標成員的建構函式
*/
LinkNode(LinkNode<T> *ptr = NULL){link=ptr;}
/*
** 初始化資料和指標成員的建構函式
*/
LinkNode(const T& item,LinkNode<T> *ptr=NULL)
{
data=item;
link=ptr;
}
};
#endif
接著實現“鏈式棧”“LinkedStack.h”
/*
** 鏈式棧的模板類及其成員函式的實現
*/
#ifndef LINKEDSTACK_H
#define LINKEDSTACK_H
#include "LinkedList.h"
#include "stack.h"
#include "stdafx.h"
#include "seqstack.h"
#include <iostream>
template<class T>
class LinkedStack:public Stack<T>{
public:
/*
** 建構函式,置空棧
*/
LinkedStack():top(NULL){};
/*
** 解構函式
*/
~LinkedStack(){makeEmpty();};
/*
** 進棧
*/
void Push(const T& x);
/*
** 退棧
*/
bool Pop(T& x);
/*
** 讀取棧頂元素
*/
bool getTop(T& x)const;
/*
** 判斷是否棧為空
*/
bool isEmpty()const{return(top==NULL)?true:false;}
/*
** 鏈式表不需要判斷是否棧滿,但必須將虛擬函式例項化,這裡預設返回為true
*/
bool isFull()const{return true;}
/*
** 求棧的元素個數
*/
int getSize()const;
/*
** 清空棧
*/
void makeEmpty();
/*
** 輸出棧中元素的過載操作<<
*/
friend ostream& operator<<(ostream& os,SeqStack<T>& s);
private:
/*
** 棧頂指標,即鏈頭指標
*/
LinkNode<T> *top;
};
template<class T>
void LinkedStack<T>::makeEmpty(){
LinkNode<T> *p;
while(top !=NULL)
{
p=top;
top=top->link;
delete p;
}
};
template<class T>
bool LinkedStack<T>::Pop(T& x)
{
if (isEmpty()==true)
{
return false;
}
LinkNode<T> *p=top;
top=top->link;
x=p->data;
delete p;
return true;
};
template<class T>
void LinkedStack<T>::Push(const T& x){
top=new LinkNode<T>(x,top);
assert(top !=NULL);
};
template<class T>
bool LinkedStack<T>::getTop(T& x)const{
if (isEmpty()==true)
{
return false;
}
x=top->data;
return true;
};
template<class T>
int LinkedStack<T>::getSize()const{
int k=0;
LinkNode<T> *p=top;
while (p !=NULL)
{
p=p->link;
k++;
}
/*
**一個成員函式宣告為const,則這個成員函式不修改資料成員,這個書裡面寫錯了
*/
/*while (top !=NULL)
{
top=top->link;
k++;
}*/
return k;
};
template<class T>
ostream& operator<<(ostream& os,LinkedStack<T>& s){
os<<"get stack size is"<<s.getSize()<<endl;
LinkNode<T> *p=s.top;
int i=0;
while(p!=NULL)
{
os<<++i<<":"<<p->data<<endl;
p=p->link;
}
return os;
};
#endif
3、Main函式呼叫
#include "stdafx.h"
#include "seqstack.h"
#include "stack.h"
#include "LinkedStack.h"
#include "LinkedList.h"
void _tmain(int argc, _TCHAR* argv[])
{
//申明一個int型的順序棧
SeqStack<int>inArray(maxSize);
//申明一個int型的鏈式棧
LinkedStack<int>linkArray;
int seqtop,linktop;
for (int i=0;i<50;i++)
{
//進棧
inArray.Push(i);
linkArray.Push(i);
//獲取棧頂元素,獲取不會進行出棧操作,可以對比下面的Pop操作對比
inArray.getTop(seqtop);
linkArray.getTop(linktop);
//輸出棧頂元素
cout<<seqtop<<" "<<linktop<<endl;
}
int size=inArray.getSize();
cout<<"the seqstack current size is "<<size<<endl;
size=linkArray.getSize();
cout<<"the linkstack current size is "<<size<<endl;
//清空棧
linkArray.makeEmpty();
size=linkArray.getSize();
cout<<"the linkstack current size is "<<size<<endl;
while(!inArray.isEmpty())
{
inArray.Pop(seqtop);
//輸出出棧元素,驗證棧是“LIFO(後進先出)”
cout<<seqtop<<endl;
cout<<"the stack current size is "<<inArray.getSize()<<endl;
}
//房子視窗退出
cin>>size;
}