栈与队列概述
1.栈
- 定义:只能在表的一端(栈顶)进行插入和删除运算的线性表。其中,表尾端称为栈顶 (top), 表头端称为栈底 (base)。 不含元素的栈称为空栈;
- 栈和队列是限定插入和删除只能在表的“端点”进行的线性表;
2.队列
- 定义:队列是一种先进先出(FIFO) 的线性表。在表一端插入,在另一端删除;
栈与队列的表示与实现
1.栈的表示
- 顺序栈的表示
**顺序表示:**利用一组地址连续的存储单 元依次存放自栈底到栈顶的数据元素。 栈底一般在低地址;
top:指示栈顶元素位置;
base:指示栈底元素位置;
stacksize:表示栈的最大容量;
空栈:base == top;
栈满:top-base = stacksize;
栈的容量:stacksize= 4;
栈满时的处理方法:
1、报错,返回;
2、分配更大的空间,作为栈的存储空间,将原栈的内容移入新栈;
- 顺序栈的表示
typedef struct{
SElemType *base; //栈底指针
SElemType *top; //栈顶指针
int stacksize; //栈可用最大容量
}SqStack;
SqStack S;
- 链栈的表示
typedef struct StackNode{
int data; //数据域
struct StackNode *next; //指针域
}stackNode,*LinkStack;
LinkStack S;
- 栈顶指针就是链表的头指针;
- 基本不存在满栈的情况;
- 空栈相当于头指针指向空;
- 插入和删除仅在栈顶处操作,不需要头结点;
2.顺序栈的实现
- 初始化
Status InitStack( SqStack &S ){
S.base =new SElemType[MAXSIZE];
if( !S.base ) return OVERFLOW; //空间分配失败
S.top = S.base; //栈顶指针=栈底指针
S.stackSize = MAXSIZE;
return OK;
}
- 入栈
Status Push( SqStack &S, SElemType e){
if( S.top- S.base== S.stacksize ) // 栈满
return ERROR;
*S.top++=e;
return OK;
}
- 出栈
Status Pop( SqStack &S, SElemType e){
if( S.top == S.base) // 栈空
return ERROR;
e= *--S.top;
return OK;
}
3.链栈的实现
- 初始化
void initStack(LinkStack &s){
s=NULL; //不需要头节点
}
//无需new,因为是不带头结点的单链表
- 栈空
int stackEmpty(LinkStack s){
if(s==NULL)
return ok;
return error;
}
- 求链栈的长度
int stackLength(LinkStack s){
int sum=0;
stackNode *temp=s;
while(temp!=NULL){
sum++;
temp=temp->next;
}
return sum;
}
- 入栈
void push(LinkStack &s,int e){
stackNode *p=new stackNode;
p->data=e;
p->next=NULL;
if(s==NULL)
s=p;
else{
p->next=s;
s=p;
}
}
- 出栈
void pop(LinkStack &s,int &e){
stackNode *p=new stackNode;
if(s==NULL){
cout<<"栈为空,无法弹出"<<endl;
}
else{
p=s;
e=p->data;
s=s->next;
delete p;
cout<<"成功弹出栈顶元素"<<endl;
}
}
3.共享栈
- 有两个相同类型的栈时,采用共享栈最大限度地利用实现开辟的存储空间来进行操作;
- 怎么判空?
top0==-1;top1==MAXSIZE;
- 怎么判满?
top1-top0 == 1;
- 怎么进栈?
0号进栈,top0先加1再赋值;1号进栈,top1先减1再赋值;
- 怎么出栈?
0号出栈,先赋值top0再减1;1号出栈,先赋值top1再加1;
队列的表示与实现
1.顺序队列的表示
#define MAXQSIZE 100 //最大队列长度
Typedef struct{
ElemType data[MAXQSIZE]; //初始化的动态分配存储空间
int *front; //头指针
int *rear; //尾指针
}SqQueue;
2.顺序队列的实现
- 初始:front=rear=0;
- J1、J2、J3依次入队 Base[rear]=x; rear++;
- J1、J2 出队操作: x=Base[front]; front++;
- J4、J5、J6入队 J3、J4出队;
是否可在队尾插入新的元素?
- 数组大小:MAXQSIZE;
- 若 front≠0 rear=MAXQSIZE,入队-假溢出;
- 若 front=0 rear=MAXQSIZE,入队-真溢出;
3.循环队列的实现
- 初始化
Status InitQueue (SqQueue &Q){
Q.base =new QElemType[MAXQSIZE] //分配最大容量的数组空间
if(!Q.base) exit(OVERFLOW); //存储分配失败
Q.front=0;
Q.rear=0; //将头指针和尾指针置为0,队列为空
return OK;
}
- 求循环队列的长度
int QueueLength (SqQueue Q){
return(Q.rear-Q.front+MAXQSIZE)%MAXQSIZE);
}
- 入队
Status EnQueue(SqQueue &Q,QElemType e){
if((Q.rear+1)%MAXQSIZE==Q.front)) //若尾指针在循环意义上加1后等于头指针,表明队满
return ERROR;
Q.base[Q.rear]=e; //新元素加入队尾
Q.rear=(Q.rear+1)%MAXQSIZE; //队尾指针加1
return OK;
}
- 出队
Status DeQueue (LinkQueue &Q,QElemType &e){
if(Q.front==Q.rear) //队空
return ERROR;
e=Q.base[Q.front]; //保存队头元素
Q.front=(Q.front+1)%MAXQSIZE; //队头指针加1
return OK;
}
4.链队列的表示
- 队列结点类型
typedef struct QNode{
QElemType data;
struct Qnode *next;
}Qnode, *QueuePtr;
- 链式队列管理结构
typedef struct {
QueuePtr front;
QueuePtr rear;
}LinkQueue;
5.链队列的实现
- 初始化
Status InitQueue (LinkQueue &Q){
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));//生成新的节点作为头结点
if(!Q.front) exit(OVERFLOW);
Q.front->next=NULL;//头结点的指针域置空
return OK;
}
- 入队
Status EnQueue(LinkQueue &Q,QElemType e){
p=(QueuePtr)malloc(sizeof(QNode)); //p=new QNode
if(!p) exit(OVERFLOW);
p->data=e; //将新节点数据域置为e
p->next=NULL; Q.rear->next=p; //将新结点插入队尾
Q.rear=p; //修改队尾指针
return OK;
}
- 出队
Status DeQueue (LinkQueue &Q,QElemType &e){
if(Q.front==Q.rear)
return ERROR; //若队为空,返回error
p=Q.front->next; //p指向队头元素
e=p->data; //e保存队头元素的值
Q.front->next=p->next; //修改头结点的指针域
if(Q.rear==p)
Q.rear=Q.front; //元素删除,指针指向头节点
delete p;
return OK;
}
- 取队头元素
Status GetHead (LinkQueue Q, QElemType &e){
if(Q.front==Q.rear)
return ERROR;
e=Q.front->next->data; //返回队头元素的值,队头指针不变
return OK;
}
站与队列的应用
1.进制转换(十进制数159转换为八进制)
void conversion(int n){
stack s;
while (n) {
s.push(n % 8);n = n/8;
}
cout << "八进制数为:";
while (!s.empty()){
cout << s.top();s.pop();
}
}
int main(){
conversion(1234);
return 0;
}
tHead (LinkQueue Q, QElemType &e){
if(Q.front==Q.rear)
return ERROR;
e=Q.front->next->data; //返回队头元素的值,队头指针不变
return OK;
}
# 站与队列的应用
## 1.进制转换(十进制数159转换为八进制)
```c
void conversion(int n){
stack s;
while (n) {
s.push(n % 8);n = n/8;
}
cout << "八进制数为:";
while (!s.empty()){
cout << s.top();s.pop();
}
}
int main(){
conversion(1234);
return 0;
}