資料結構筆記三: 棧
阿新 • • 發佈:2019-01-12
1. 棧的基本概念
棧是限定只在表頭進行插入(入棧)和刪除(出棧)操作的線性表,表頭端稱為棧頂,表尾端稱為棧底。
設有棧
則一般稱
為棧底元素,
為棧頂元素,按
的順序依次進棧,出棧的第一個元素為棧頂元素,也就是說棧是按照後進先出的原則進行。
棧的實現和線性表類似,有兩種方法——順序棧和鏈棧
2. 順序棧
//.hpp檔案
#pragma once
#define DEFAULT_SIZE 10
//順序棧類
template<typename elemType>
class SqStack
{
private:
//順序棧的資料成員
int count;
int maxSize;
elemType* elems;
//輔助函式
bool Full() const; //判斷棧是否已滿
void Init(int size);//對棧進行初始化
public:
//抽象資料型別方法宣告及過載編譯系統預設方法宣告
SqStack(int size = DEFAULT_SIZE);//建構函式
virtual ~SqStack();//解構函式
int getLength() const;//求棧的長度
bool isEmpty() const;//判斷棧是否為空
void Clear();//清空棧
void Traverse(void(*Visit)(elemType &));//遍歷棧
bool Push(const elemType &e);//入棧
bool Top(elemType &e) const;//返回棧頂元素
bool Pop(elemType &e);//出棧
SqStack(SqStack<elemType> ©);//複製建構函式
SqStack<elemType>& operator=(SqStack<elemType> ©);//賦值運算子過載
};
//順序棧的實現
template<typename elemType>
bool SqStack<elemType>::Full() const
{
return count == maxSize;
}
template<typename elemType>
void SqStack<elemType>::Init(int size)
{
maxSize = size;
if (elems != NULL) delete[] elems;
elems = new elemType[maxSize];
count = 0;
}
template<typename elemType>
SqStack<elemType>::SqStack(int size = DEFAULT_SIZE)
{
elems = NULL;
Init(size);
}
template<typename elemType>
SqStack<elemType>::~SqStack()
{
if (elems != NULL) delete[] elems;
}
template<typename elemType>
int SqStack<elemType>::getLength() const
{
return count;
}
template<typename elemType>
bool SqStack<elemType>::isEmpty() const
{
return count == 0;
}
template<typename elemType>
void SqStack<elemType>::Clear()
{
count = 0;
}
template<typename elemType>
void SqStack<elemType>::Traverse(void(*Visit)(elemType &))
{
for (int curPosition = 1; curPosition <= this->getLength(); curPosition++)
{
(*Visit)(elems[curPosition - 1]);
}
}
template<typename elemType>
bool SqStack<elemType>::Push(const elemType &e)
{
if (Full())
{
return false;
}
else
{
elems[count++] = e;
return true;
}
}
template<typename elemType>
bool SqStack<elemType>::Top(elemType &e) const
{
if (isEmpty())
{
return false;
}
else
{
e = elems[count - 1];
return true;
}
}
template<typename elemType>
bool SqStack<elemType>::Pop(elemType &e)
{
if (isEmpty())
{
return false;
}
else
{
e = elems[--count];
return true;
}
}
template<typename elemType>
SqStack<elemType>::SqStack(SqStack<elemType> ©)
{
elems = NULL;
Init(copy.maxSize);//這裡為什麼可以直接訪問私有成員maxSize
count = copy.getLength();
for (int curPosition = 1; curPosition <= count; curPosition++)
{
elems[curPosition - 1] = copy.elems[curPosition - 1];
}
}
template<typename elemType>
SqStack<elemType>& SqStack<elemType>::operator =(SqStack<elemType> ©)
{
if (© != this)
{
Init(copy.maxSize);
count = copy.getLength();
for (int curPosition = 1; curPosition <= count; curPosition++)
{
elems[curPosition - 1] = copy.elems[curPosition - 1];
}
}
return *this;
}
//測試檔案
#include <iostream>
#include "SqStack.hpp"
using namespace std;
template<typename elemType>
void Visit2(elemType &e)
{
cout << e << endl;
}
int main(int argc, char* argv[])
{
SqStack<int> mySqStack;
mySqStack.Push(1);
mySqStack.Push(2);
mySqStack.Traverse(Visit2);//使用函式指標!!!
SqStack<int> mySqStack1(mySqStack);
mySqStack1.Traverse(Visit2);
getchar();
return 0;
}
3. 連結串列棧
在程式中同時使用多個棧的情形下,使用鏈式棧不但可以提高儲存效率,同時還可以達到共享儲存空間的目的。(如何達到共享儲存空間的目的?)
//.hpp檔案
#pragma once
//節點類
template<typename elemType>
struct Node
{
//資料成員
elemType data;//資料域
Node<elemType>* next;//指標域
//建構函式
Node();//無參建構函式
Node(elemType item, Node<elemType>* Link = NULL);//已知資料域和指標域建立結構
};
//節點類的實現部分
template<typename elemType>
Node<elemType>::Node()
//操作結果:構造指標域為空的節點
{
this->next = NULL;
}
template<typename elemType>
Node<elemType>::Node(elemType item, Node<elemType>* Link)
//操作結果:構造資料域為item指標域為Link的節點
{
this->data = item;
this->next = Link;
}
//鏈棧類
template<typename elemType>
class LinkStack
{
private:
//鏈棧實現的資料成員
Node<elemType>* top;//棧頂指標
//輔助函式
void Init();//初始化棧
public:
//抽象資料型別方法宣告及過載編譯系統預設方法宣告
LinkStack();//無參建構函式
virtual ~LinkStack();//解構函式
int getLength() const;//獲取棧的長度
bool isEmpty() const;//判斷棧是否為空
void Clear();//將棧清空
void Traverse(void(*Visit)(elemType &e));//遍歷棧
bool Push(const elemType & e);//入棧
bool Top(elemType& e) const;//返回棧頂的元素
bool Pop(elemType& e);//出棧
LinkStack(LinkStack<elemType> & copy);//複製建構函式
LinkStack<elemType>& operator=(LinkStack<elemType> & copy);//過載賦值運算子
};
//鏈棧類的實現
template<typename elemType>
void LinkStack<elemType>::Init()
//對鏈棧進行初始化,外部不可呼叫
{
top = NULL;
}
template<typename elemType>
LinkStack<elemType>::LinkStack()
{
Init();
}
template<typename elemType>
LinkStack<elemType>::~LinkStack()
{
Clear();
}
template<typename elemType>
int LinkStack<elemType>::getLength() const
{
int count = 0;
for (Node<elemType>* curPosition = top; curPosition != NULL; curPosition = curPosition->next)
{
count++;
}
return count;
}
template<typename elemType>
bool LinkStack<elemType>::isEmpty() const
{
return top == NULL;
}
template<typename elemType>
void LinkStack<elemType>::Clear()
{
elemType e;
while (top != NULL)
{
Pop(e);//刪除連結串列元素的技巧
}
}
template<typename elemType>
void LinkStack<elemType>::Traverse(void(*Visit)(elemType &e))
{
for (Node<elemType>* curPosition = top; curPosition != NULL; curPosition = curPosition->next)
{
(*Visit)(curPosition->data);
}
}
template<typename elemType>
bool LinkStack<elemType>::Push(const elemType & e)
{
Node<elemType>* tempNode = top;
top = new Node < elemType > ;
if (top == NULL)//如果動態記憶體耗盡
{
return false;
}
top->data = e;
top->next = tempNode;
return true;
}
template<typename elemType>
bool LinkStack<elemType>::Top(elemType& e) const
{
if (isEmpty())
{
return false;
}
else
{
e = top->data;
return true;
}
}
template<typename elemType>
bool LinkStack<elemType>::Pop(elemType& e)
{
if (isEmpty())
{
return false;
}
else
{
e = top->data;
Node<elemType>* tempPtr = top;
top = top->next;
delete tempPtr;
return true;
}
}
template<typename elemType>
LinkStack<elemType>::LinkStack(LinkStack<elemType> & copy)
{
if (copy.isEmpty())
{
Init();
}
else
{
top = new Node<elemType>(copy.top->data);
Node<elemType>* tempPtr = top;
for (Node<elemType>* curPosition = copy.top->next; curPosition != NULL; curPosition = curPosition->next)
{
tempPtr->next = new Node<elemType>(curPosition->data);
tempPtr = tempPtr->next;
}
}
}
template<typename elemType>
LinkStack<elemType>& LinkStack<elemType>::operator=(LinkStack<elemType> & copy)
{
if (© != this)
{
if (copy.isEmpty())
{
Init();
}
else
{
Clear();
top = new Node<elemType>(copy.top->data);
Node<elemType>* tempPtr = top;
for (Node<elemType>* curPosition = copy.top->next; curPosition != NULL; curPosition = curPosition->data)
{
tempPtr->next = new Node<elemType>(copy.top->data);
tempPtr = tempPtr->next;
}
}
}
return *this;
}
//測試檔案
#include "LinkStack.hpp"
#include <iostream>
using namespace std;
template<typename elemType>
void Visit2(elemType &e)
{
cout << e << endl;
}
int main(int argc, char* argv[])
{
LinkStack<int> myLinkStack;
using namespace std;
myLinkStack.Push(1);
myLinkStack.Push(2);
myLinkStack.Push(3);
myLinkStack.Traverse(Visit2);//使用函式指標!!!
LinkStack<int> mySqStack1(myLinkStack);
mySqStack1.Traverse(Visit2);
getchar();
return 0;
}