栈
栈的定义
栈(stack)又名堆栈,一种可以实现”先进后出”的存储结构,栈类似于箱子它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。栈的运算主要有置空栈、判栈空、判栈满、进栈、退栈、和取栈顶元素6种。
基本算法
进栈(PUSH)算法
①若TOP≥n时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);
②置TOP=TOP+1(栈指针加1,指向进栈地址);
③S(TOP)=X,结束(X为新进栈的元素);
退栈(POP)算法
①若TOP≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈, 空则下溢;不空则作②);
②X=S(TOP),(退栈后的元素赋给X):
③TOP=TOP-1,结束(栈指针减1,指向栈顶)。
C++代码实现
#include <iostream>
#include <stdio.h>
#include <malloc.h>
class SqStack{
private:
enum { MaxSize = 100 };
int data[MaxSize];
int top;
public:
SqStack();
~SqStack();
bool isEmpty();
void pushInt(int x);
int popInt();
int getTop();
void display();
};
SqStack::SqStack()
{
top = -1;
}
SqStack::~SqStack() {}
bool SqStack::isEmpty(){ //判断栈为空
return(top == -1);
}
void SqStack::pushInt(int x){ //元素进栈
if (top == MaxSize - 1){
std::cout << "栈上溢出!" << std::endl;
}else{
++top;
data[top] = x;
}
}
int SqStack::popInt(){ //退栈
int tmp = 0;
if (top == -1){
std::cout << "栈已空!" << std::endl;
}else{
tmp = data[top--];
}
return tmp;
}
int SqStack::getTop(){ //获得栈顶元素
int tmp = 0;
if (top == -1){
std::cout << "栈空!" << std::endl;
}else{
tmp = data[top];
}
return tmp;
}
void SqStack::display(){ //打印栈里元素
std::cout << "栈中元素:" << std::endl;
for (int index = top; index >= 0; --index){
std::cout << data[index] << std::endl;
}
}
int main(){
SqStack st;
std::cout << "栈空:" << st.isEmpty() << std::endl;
for (int i = 1; i < 10; i++){
st.pushInt(i);
}
st.display();
std::cout << "退一次栈" << std::endl;
st.popInt();
std::cout << "栈顶元素:" << st.getTop() << std::endl;
st.popInt();
st.display();
return 0;
}
队列
队列定义
队列(Queue)。队列简称队。是一种操作受限的线性表,只允许在表的一端进行插入,而在表的另一端进行删除。向队列中插入元素称为入队或进队;删除元素称为出队或离队。其操作特性为先进先出(First In First Out,FIFO),并且只允许在队尾进,队头出。队列的基本操作有:初始化队列,构造一个空队列Q;判断一个队列是否为空;入队,若队列未满,则将x加入使之成为新队尾;出队,若队列非空,则将队首元素删除,并用x返回;读队头元素,若栈顶元素非空,则用x返回栈顶元素
循环队列
将队列臆造成一个环状的空间,即把存储队列元素的表从按逻辑上视为一个环,称为循环队列。当队首指针 Q.front == MAXSIZE - 1,再前景一个位置就自动到0,这可以利用除法取余运算(%) 来实现
循环队列的操作
初始化
void InitQueue(SqQueue& Q){
Q.front = Q.rear = 0;
}
判断队空
bool QueueEmpty(SqQueue Q){
if( Q.front == Q.rear){
return true;
}
return false;
}
入队
bool EnQueue(SqQueue& Q, ElemType x){
if( (Q.rear + 1) % MAXSIZE == Q.front ){
return false;
}
Q.data[Q.rear] = x;
Q.rear = ( Q.rear + 1) % MAXSIZE;//队尾指针加1取模,这步操作很容易写错
return true;
}
出队
bool DeQueue(SqQueue& Q, ElemType &x){
if( Q.rear == Q.front ){
return false;
}
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MAXSIZE;//队头指针加1取模
return true;
}
链式队列的基本操作
初始化
void InitQueue(LinkQueue& Q){
//初始化时,Q.front 和 Q.rear 同时指向头结点
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
Q.front->next = nullptr;
}
判断队空
bool QueueEmpty(LinkQueue Q){
if( Q.front == Q.rear){
return true;
}
return false;
}
入队
bool EnQueue(LinkQueue& Q, ElemType x){
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = nullptr;
Q.rear->next = s;
Q.rear = s;
return true;
}
出队
bool DeQueue(LinkQueue& Q, ElemType &x){
if( Q.rear == Q.front ){
return false;
}
LinkNode* p = Q.front->next; //因为有头结点,所以队头节点为Q.front->next
x = p->data;
Q.front->next = p->next;
if( Q.rear == p ){ //只剩一个结点,删除后变空只剩头结点
Q.rear = Q.front;
}
free(p);
return true;
}