栈是只允许在一端进行插入或删除操作的线性表
n个不同元素进栈,出栈元素不同排列的个数为Cn2n/n+1
顺序栈
//顺序栈的定义
typedef struct{
ElemType data[MaxSize];
int top;//栈顶指针,指向栈顶元素,返回数组下标压入4各元素该指针就是4
}SqStack;
//判断栈空
bool StackEmpty(SqStack S){
if(S.top==-1)
return true;
else
return false;
}
//初始化
void InitStack(SqStack &S){
S.top=-1;
}
//新元素入栈
bool Push(SqStack &S ,ElemType x){
if(S.top==MaxSize-1)//栈满
S.top=S.top+1;//
S.data[S.top]=x;//S.data[++S.top]=x;
return true;
}
//出栈操作
bool Push(SqStack &S ,ElemType &x){
if(S.top==-1)//栈空
return false;
x=S.data[S.top];//
S.top=S.top-1;//x=S.data[S.top--];
return true;
}
//读栈顶元素
bool Push(SqStack &S ,ElemType &x){
if(S.top==-1)//栈空
return false;
x=S.data[S.top];//x记录栈顶元素
return true;
}
void testStack(){
SqStack S;//声明一个顺序栈
InitStack(S);
}
链栈
队列
队列是只允许在一端进行插入,在另一端删除的线性表
!注意
rear在队尾元素下一位:先赋值再移动指针
rear指向队尾元素:先移动指针再赋值,在初始化时front指向0位置,rear指向n-1位置
顺序存储
//队列的顺序实现
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
//判空
bool QueueEmpty(SqQueue Q){
if(Q.rear==Q.front)
return true;
else
return false;
}
//入队
bool QueueEmpty(SqQueue &Q,ElemType x){
if((Q.rear+1)%MaxSize==Q.front)//队满条件:队尾指针的再下一个位置是队头
return false;
Q.data[Q.rear]=x;//x插入对尾
Q.rear=(Q.rear+1)%MaxSize;//让rear指针循环往复
return true;
}
//
bool QueueEmpty(SqQueue &Q,ElemType &x){
if(Q.rear==Q.front)//队满条件:队尾指针的再下一个位置是队头
return false;
x=Q.data[Q.rear];//x插入对尾
Q.rear=(Q.rear+1)%MaxSize;//让rear指针循环往复
return true;
}
链式存储
//队列的链式实现
typedef struct{ //链式队列结点
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{ //链式队列
LinkNode *front,*rear;
}LinkNodeQueue;
//初始化 带头节点
void InitQueue(LinkQueue &Q){
Q.fronr=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q,front->next=NULL;
}
//判空 Q.front==Q.rear
//初始化 不带头节点
void InitQueue(LinkQueue &Q){
Q,front=NULL;
Q.rear=NULL;
}
//判空 Q.front==NULL
//入队(带头节点)
void EnQueue(LinkNodeQueue &Q,ElemType x){
LinkNode *s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;//插入到队尾,所以连接NULL
Q,rear->next=s;
Q.rear=s;//rear指向新的表尾节点
}
//入队(不带头节点)
void EnQueue(LinkNodeQueue &Q,ElemType x){
LinkNode *s=(LinkNode*)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;//插入到队尾,所以连接NULL
if(Q.front == NULL){ //在空队中插入第一个元素
Q.front=s;//修改对头队尾指针
Q.rear=s;
}else{
Q,rear->next=s;
Q.rear=s;//rear指向新的表尾节点
}
}
//出队(带头节点)
bool DeQueue(LinkNodeQueue &Q,ElemType &x){
if(Q.front==Q.rear)
return false;
LinkNode *p=Q.front->next;//指向头结点的后面一个节点即要删除的节点
x=p->data;//x返回队头元素
Q.front->next=p->next;
if(Q.rear==p)//此次是最后一个节点出队
Q.rear=Q.front;
free(p);
return true;
}
//出队(不带头节点)
bool DeQueue(LinkNodeQueue &Q,ElemType &x){
if(Q.front==Q.rear)
return false;
LinkNode *p=Q.front;//指向头结点的后面一个节点即要删除的节点
x=p->data;//x返回队头元素
Q.fron=p->next;
if(Q.rear==p)//此次是最后一个节点出队
Q,front=NULL;
Q.rear=NULL;
free(p);
return true;
}
队列的应用:树的层次遍历、图的广度遍历,多个进程抢占系统资源时先来先服务 eg:数据缓冲区
特殊矩阵的压缩存储
栈在表达式求值中的应用
栈在递归中的应用
适合用递归算法解决:可以把原始问题转换为属性相同,但规模较小的问题
实现递归算法需要注意:(1)递归表达式(2)递归出口
每进入一层递归,就将递归调用所需信息压入栈顶
每退出一层递归,就从栈顶弹出相应信息
缺点:效率低,太多层递归可能会导致栈溢出;可能包含很多重复计算
//计算正整数 n!
int factoral(int n){
if(n==0 || n==1)
return 1;
else
return n*factoral(n-1);
}
int main(){
int x=factoral(10);
}