1. 堆栈
- 什么是堆栈? 堆栈(Stack):具有一定操作约束的线性表
只在一端(栈顶,Top)做插入、删除
插入数据:入栈(Push)
删除数据:出栈(Pop)
后入先出:Last In First Out(LIFO)
2.栈的顺序存储实现(C与C++的区别) (通常把空栈的条件判定为top=-1)
主要是对top指针进行一系列的操作!!!!!! 二者都有两个指针,头指针top和栈顶指针maxsize
2.1 模板
c++
#include <iostream>
using namespace std;
//堆栈基类
template <typename T>
class Stack{
public: // =0为纯虚函数
virtual bool IsEmpty() const = 0; //若栈空,则返回true
virtual bool IsFull() const = 0; //若栈满,则返回true
virtual bool Top(T &x) const = 0; //在x中返回栈顶元,若操作成功,则返回true
virtual bool Push(T x) = 0; //在栈顶插入元素x(入栈),若操作成功,则返回true
virtual bool Pop() = 0; //从栈中删除栈顶元素(出栈),若操作成功,则返回true
virtual void Clear() = 0; //清除栈中全部元素
};
//堆栈的顺序表示
template <typename T>
class SeqStack:public Stack<T>{
private:
int top; //栈顶指针
int maxTop; //最大栈顶指针
T* s;
public:
SeqStack(int mSize);
~SeqStack();
bool IsEmpty() const; //若栈空,则返回true
bool IsFull() const; //若栈满,则返回true
bool Top(T &x) const; //在x中返回栈顶元,若操作成功,则返回true
bool Push(T x); //在栈顶插入元素x(入栈),若操作成功,则返回true
bool Pop(); //从栈中删除栈顶元素(出栈),若操作成功,则返回true
void Clear(); //清除栈中全部元素
}
c:
类型名称:堆栈(Stack)
数据对象集:一个有 0 个或多个元素的有穷线性表
操作集:长度为 MaxSize 的堆栈 S ∈ Stack,堆栈元素 item ∈ ElementType
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成
堆栈的基本操作主要有:
#include<stdio.h>
#include<malloc.h>
#define MaxSize 100 // 堆栈元素的最大个数
typedef int ElementType; // ElementType 暂时定义为 int 类型
struct SNode{
ElementType Data[MaxSize]; // 存储堆栈元素
int Top; // 记录栈顶元素下标
};
typedef struct SNode *Stack;
Stack S;
Stack CreateStack(int MaxSize):生成空堆栈,其最大长度为 MaxSize
int IsFull(Stack S,int MaxSize):判断堆栈 S 是否已满
void Push(Stack S,ElementType item):将元素 item 压入堆栈
int IsEmpty(Stack S):判断堆栈 S 是否为空
ElementType Pop(Stack S):删除并返回栈顶元素
2.2 初始化构造堆栈 (通常把空栈的条件判定为top=-1)
c++
template <typename T>
SeqStack<T>::SeqStack(int mSize) {
maxTop = mSize - 1;
s = new T[mSize];
top = -1;
}
c
// 初始化堆栈
Stack CreateStack(){
S = (Stack)malloc(sizeof(struct SNode));
S->Top = -1;
return S;
}
2.3 析构函数
template <typename T>
SeqStack<T>::~SeqStack() {
delete[] s;
}
2.4 是否为空
template <typename T>
bool SeqStack<T>::IsEmpty() const {
return -1 == top;
}
// 是否为空
int IsEmpty(Stack S){
return (S->Top == -1); // == 的意思是是否等于,返回true或者false
}
2.5 是否已满
c++
template <typename T>
bool SeqStack<T>::IsFull() const {
return top == maxTop; // == 的意思是是否等于,返回true或者false
}
c
// 是否已满
int IsFull(Stack S){
return (S->Top == MaxSize-1);
}
2.6 入栈
c++
template <typename T>
bool SeqStack<T>::Push(T x) {
if (IsFull()) {
cout << "Full" << endl;
return false;
}
s[++top] = x;
return true;
}
c
// 入栈
void Push(Stack S,ElementType item){
if(IsFull(S)){ // Top 从 0 开始
printf("堆栈满");
return;
}else{
S->Top++; // 栈顶元素加一
S->Data[S->Top] = item; // 放进最上
return;
}
}
2.7 出栈
c++
template <typename T>
bool SeqStack<T>::Pop() {
if (IsEmpty()) {
cout<<"Empty"<<endl;
return false;
}
top--;
return true;
}
C
// 出栈
ElementType Pop(Stack S){
if(IsEmpty(S)){
printf("堆栈空");
return;
}else{
ElementType val = S->Data[S->Top]; //取出最上
S->Top--; // 栈顶元素减一
return val;
}
}
2.8 清空(only c++)
c++
template <typename T>
void SeqStack<T>::Clear() {
top = -1;
}
2.9 测试
c
int main(){
S = CreateStack();
printf("5入栈\n");
Push(S,5);
printf("7入栈\n");
Push(S,7);
printf("66入栈\n");
Push(S,66);
printf("%d出栈\n",Pop(S));
printf("%d出栈\n",Pop(S));
return 0;
}
3.栈的链式存储实现 – 链栈 (单链表的头结点作为栈顶) (通常把空栈的条件判定为 next=NULL )
栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行
3.1 模板
c++
表头指针的next永远指向栈顶。
//堆栈的链接表示
template <typename T>
class SingleStack;
template <typename T>
class Node{
private:
T element;
Node<T>* next;
friend class SingleStack<T>;
};
template <typename T>
class SingleStack:public Stack<T>{
private:
Node<T>* head;
bool IsFull() const{};
public:
SingleStack();
~SingleStack();
bool IsEmpty() const; //若栈空,则返回true
bool Top(T &x) const; //在x中返回栈顶元,若操作成功,则返回true
bool Push(T x); //在栈顶插入元素x(入栈),若操作成功,则返回true
bool Pop(); //从栈中删除栈顶元素(出栈),若操作成功,则返回true
void Clear(); //清除栈中全部元素
};
c
#include<stdio.h>
#include<malloc.h>
typedef int ElementType;
typedef struct SNode *Stack;
struct SNode{
ElementType Data;
Stack Next;
};
Stack CreateStack(); // 初始化链栈
int IsEmpty(Stack S); // 判断链栈是否为空
void Push(Stack S,ElementType item); // 入栈
ElementType Pop(Stack S); // 出栈
3.2 初始化构造
c++
template <typename T>
SingleStack<T>::SingleStack() {
head = new Node<T>;
head->next = NULL; //head是一个空栈
}
C
// 初始化
Stack CreateStack(){
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
3.3 析构函数
C++
template <typename T>
SingleStack<T>::~SingleStack() {
Node<T> *p;
while (head != NULL) {
p = head;
head = head->next;
delete (p);
}
}
3.4 是否为空
C++
template <typename T>
bool SingleStack<T>::IsEmpty() const {
if (head->next == NULL) {
return true;
} else {
return false;
}
}
C
// 判断是否为空
int IsEmpty(Stack S){
return (S->Next == NULL);
}
3.5 入栈
C++
template <typename T>
bool SingleStack<T>::Push(T x) {
Node<T>* newNode = new Node<T>;
newNode->element = x;
newNode->next = head->next; //?????????????????????????????????????????????? 太混乱了???
head->next = newNode;
}
C
入栈是放在头结点后面的第一个节点!!!!!!
// 入栈
void Push(Stack S,ElementType item){
Stack tmp;
tmp = (Stack)malloc(sizeof(struct SNode)); //申请一个结点
tmp->Data = item;
// 链栈栈顶元素是链表头结点,新入栈的链表在栈顶元素后面
tmp->Next = S->Next; // 所以这个next就好理解了!!!!!!为什么??==单链表的头结点作为栈顶==
S->Next = tmp;
}
3.6 出栈
C++
template <typename T>
bool SingleStack<T>::Pop() {
if (IsEmpty()) {
cout<<"Empty"<<endl;
return false;
}
Node<T>* p = head->next;
head->next = p->next;
delete (p);
}
C
释放一个结点,就必须把这个结点值赋值给一个变量????
举个非程序形式的例子:
A -> B -> C ->D
如果要删除B,并且保持链表结构正常的话
需要 一个中间变量 TMP
B的地址赋值给TMP
Tmp = B
由A获取C的地址
A = C
这时再删除B
DEL B
就完成了
还有一个问题?这个栈顶的头指针top指向的是谁??应该是头结点后面的第一个的结点!!!!!!!!!!!!!!!!
// 出栈
ElementType Pop(Stack S){
Stack First;
ElementType TopVal;
if(IsEmpty(S)){
printf("堆栈空");
return;
}else{
First = S->Next; // 出栈第一个元素在栈顶元素后面
S->Next = First->Next; //把第一个元素从链栈删除
TopVal = First->Data; // 取出被删除结点的值
free(First); // 释放空间
return TopVal;
}
}
3.7 链栈的清空
C++
template <typename T>
void SingleStack<T>::Clear() {
Node<T> *p = head->next;
head->next = NULL;
Node<T> *q;
while (p != NULL) {
q = p;
p = p->next;
delete (q);
}
}
3.8 测试
C
int main(){
Stack S;
S = CreateStack();
printf("5入栈\n");
Push(S,5);
printf("7入栈\n");
Push(S,7);
printf("66入栈\n");
Push(S,66);
printf("%d出栈\n",Pop(S));
printf("%d出栈\n",Pop(S));
return 0;
}