栈:只允许在一端进行插入或删除操作的线性表 特点:后进先出 Last In First Out(LIFO)
1. 顺序栈的创建
#define MaxSize 10 //定义栈中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
void testStack() {
SqStack S; //声明一个顺序栈(分配空间)
}
2. 初始化栈
void InitStack(SqStack &S) {
S.top = -1; //初始化栈顶指针
}
//判断栈是否为空
bool StackEmpty(SqStack S) {
if(S.top == -1)
return true;
else
return false;
}
3. 进栈操作
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1)
return false;
S.top += 1;
S.data[S.top] = x;
return true;
}
4. 出栈操作
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1)
return false;
x = S.data[S.top];
S.top = S.top-1;
return true;
}
1. 链栈的定义(与单链表类似)
typedef struct Linknode{
ElemType data; //数据域
struct Linknode *next; //指针域
}*LiStack;
链表的头结点——>栈顶,进栈/出栈都只能在栈顶一端进行
1. 队列只允许在一端进行插入(入队),另一端进行删除的线性表(出队)。
重要术语:队头、队尾、空队列
队列的特点:先进先出,FIFO
2. 初始化队列
#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q){
Q.rear=Q.front=0;
}
3. 入队操作(只能从队尾入队)
bool EnQueue(SqQueue &Q,EleType x){
if((Q.rear+1)%MaxSize==Q.front){
return false;
}
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
}
4. 出队操作(只能从队头出队)
bool EnQueue(SqQueue &Q,EleType x){
if((Q.rear+1)%MaxSize==Q.front){
return false;
}
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
}
tip:计算队列元素的个数length=(rear+MaxSize-front)%MaxSize
1. 队列的链式实现
typedef struct LinkNode{
EleType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear;
}LinkQueue;
2. 初始化队列
带头结点
void InitQueue(LinkQueue &Q){
Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
不带头结点
void InitQueue(LinkQueue &Q){
Q.rear=NULL;
Q.front=NULL;
}
3. 入队操作
带头结点
void EnQueue(LinkNode &Q,ElemType x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;
}
不带头结点
void EnQueue(LinkNode &Q,ElemType x){
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
//第一个插入元素需要特殊处理
if(Q.front==NULL){
Q.front=s;
Q.rear=s;
}else{
Q.rear->next=s;
Q.rear=s;
}
}
4. 出队操作
带头结点
bool DeQueue(LinkNode &Q,ElemType &x){
if(Q.front==Q.rear)
return flase;
x=Q.front->data;
LinkNode *p=Q.front->next;
x=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return true;
}
不带头结点
bool DeQueue(LinkNode &Q,ElemType &x){
if(Q.rear==NULL)
return flase;
LinkNode *p=Q.front;
x=p->data;
Q.front->next=p->next;
if(Q.rear==p){
Q.rear=NULL;
Q.front==NULL;
}
free(p);
return true;
}
双端队列:允许从两端插入、两端删除
#define MaxSize 10
typedef struct{
char data[MaxSize];
int top;
}SqStack;
//判断队列是否为空
bool isEmpty(SqStack S){
if(top==-1)
return true;
return false;
}
//初始化队列
void initStack(SqStack &S){
S.top=-1;
}
//入列
bool Push(SqStack &S,char x){
if(S.top==MaxSize-1)
return false;
S.top+=1;
S.data[S.top]=x;
return true;
}
//出列
bool Pop(SqStack &S,char &x){
if(S.top==-1)
return false;
x=S.data[S.top];
S.top-=1;
return true;
}
bool bracketCheck(char str[],int length){
SqStack S;
initStack(S);
for(int i=0;i
1. 函数调用时,需要用一个栈存储:
①调用返回地址;
②实参;
③局部变量。
2. 递归:把原始问题转换为属性相同,但规模较小的问题
递归算法的缺点:效率低,太多层递归可能会导致栈溢出,可能会包含很多重复运算
解决方案:可以自定义栈将递归算法改造为非递归算法。