栈和队列
栈(Stack)
定义与特点
栈是一种特殊的线性表,只能从一端进行插入和删除——>后进后出 LIFO结构
表尾(an) 称为栈顶Top 表头(a1)称为栈底Base
插入元素到栈顶的操作称为入栈
删除栈顶最后一个元素的操作称为出栈
抽象类型定义
ADT Stack{
数据对象:D = {ai|ai∈ElemSet,i=1,2,3,...n,n≥0}
数据关系:R1 = {<ai-1,ai>|ai-1,ai∈D,i=2...,n}约定an端为栈顶,a1端为栈底
基本操作:初始化,进栈,出栈,取栈元素等
}ADT Stack
基础操作
InitStack(&S):初始化一个空栈S。
StackEmpty(S):判断一个栈是否为空
StackLength(S):求栈长度
Push(&S, x):进栈——栈的插入操作
Pop(&S, &x):出栈——栈的删除操作
GetTop(S, &e):读栈顶元素
ClearStack(&S):栈置空
DestroyStack(&S):栈销毁
顺序栈
为方便top指针指向栈顶元素之上的下标地址
stacksize ——> 栈可使用的最大容量
空栈的标志:base == top
栈满的标志: top - base == stacksize
———— 元素个数计算即top - base
上溢:栈满进行插入 下溢:栈空继续弹出
顺序栈的数据类型定义
#define MAXSIZE 100
typedef struct{SElemType *base;//栈底指针SElemType *top;//栈顶指针int stacksize;//栈可用最大容量
}SqStack;
顺序栈的初始化
Status lnitStack(SqStack &S)
{S.base = new SElemType[MAXSIZE];if(!S.base) exit (OVERFLOW);//存储分配成功S.top = S.base;S.stacksize = MAXSIZE;return OK;
}
判断顺序栈是否为空
Status StackEmpty(SqStack S)
{if(S.top == S.base)return TURE;elsereturn FALSE;
}
求顺序栈的长度
int StackLength(SqStack S)
{return S.top - S.base;
}
清空顺序栈
Status ClearStack(SqStack S){if(S.base) S.top = S.base;return OK;
}
销毁顺序栈
Status DestroyStack(SqStack &S){if(S.base){delete S.base;S.stacksize == 0;S.base = S.top = NULL;}return OK;
}
顺序栈的入栈
1.判断栈是否满,若满则出差(上溢)
2.元素e压入栈顶
3.栈顶指针加1
Status Push(SqStack &S, SElemType e){if(S.top - S.base == S.stacksize)return ERROR;*S.top++ = e; //先e赋值给*S.top再移动指针++return OK;}
}
顺序栈的出栈
1.判断栈是否为空,空则出错(下溢)
2.获取栈顶元素e
3.栈顶指针-1
Status Pop(SqStack &S, SElemType &e){if(S.top == S.base)return ERROP;e = *--S.top;return OK;
}
链栈
链栈指针方向与链表方向相反
· 链表的头指针就是栈顶
· 不需要头节点
· 基本不存在栈满的情况
· 空栈相当于头指针指向空
· 插入和删除仅在栈顶处执行
数据类型定义
typedef struct StackNode{SElemType date;struct StackNode *next;
}StackNode,*LinkStack;
LinkStack S;
初始化
void lnitStack(LinkStack &S){S = NULL;return OK;
}
判断链栈是否为空
Status StackEmpty(LinkStack S){if(S == NULL) return TURE;else return FlASE;
}
链栈入栈
Status Push(LinkStac &S,SElemType e){p = new StackNode;p -> date = e;P -> next = S;S = p;return OK;
}
链栈出栈
Status Pop(LinkStac &S,SElemType &e){if(S == NULL) return ERROR;e = S -> date;p = S;S = S -> next;delete p;return OK;
}
取栈顶元素
SElemType GetTop(LinkStack S){if(S!= NULL)return S -> date;
}
栈与递归
一个对象包含自己或自己给自己定义
一个过程直接或间接调用自己
分治法求递归问题算法的一般形式
void p(参数表){if(递归结束条件) 可以直接求解步骤; ——基本项else p(较小的参数); ——归纳项
}
队列(queue)
队列是一种先进先出的线性表(FIFO)
一端插入一端删除
抽象类型定义
ADT Queue{
数据对象:D = {ai|ai∈ElemSet,i=1,2,3,...n,n≥0}
数据关系:R1 = {<ai-1,ai>|ai-1,ai∈D,i=2...,n}约定a1端为队列头,an端为队列尾
基本操作:初始化,入队,出队等
}ADT Queue
基础操作
InitQueue (&Q) 构造空队列
DestroyQueue (&Q) 销毁队列
ClearQueue (&Q) 清空队列
QueueEmpty(Q) 判空. 空=TRUE,
QueueLength(Q) 取队列长度
GetHead (Q,&e) 取队头元素,
EnQueue (&Q,e) 入队列
DeQueue (&Q,&e) 出队列
QueueTraverse(Q,visit()) 遍历
顺序队列
一维数组base[MAXQSIZE]表示
#define MAXQSIZE 100 //最大队列长度
Typedef struct{QElemType *base; //初始化的动态分配存储空间int front; //头指针int rear; //尾指针
}SqQueue
初始状态 front = rear = 0
当 rear = MAXQSIZE
时发生溢出
若front = 0 rear = MAXQSIZE时
再入队 则为真溢出
若front != 0 rear = MAXQSIZE时
再入队 则为假溢出
对于假上溢如何解决 >>>
1.将对内元素依次向队头方向移动 (浪费时间)
2.循环:思路:base[0] 接在 base[MAXQSIZE-1] 之后 ,若 rear + 1 == MAXQSIZE, 则令 rear = 0;具体实现:用%的运算
插入元素:Q.base[Q.rear] = x;Q.rear = (Q.rear + 1) % MAXQSIZE;
删除元素:x = Q.base[Q.front]Q.front = (Q.front + 1 ) % MAXQSIZE
对于判断循环队空队满 >>>
当循环队列中队空队满都为 front == rear 如何解决
1.设标记
2.记录个数
3.少用一个元素空间 则队满: (rear + 1) % MAXQSZIE == front
初始化
Status lnitQueue(SqQueue &Q){Q.base = new QElemType[MAXQSIZE];if(!Q.base) exit(OVERFLOW);Q.front = Q.rear = 0;return OK;
}
求队列长度
int QueueLength(SqQueue Q){return ((Q.rear - Q.front + MAXQSZIE) % MAXQZIE);
}
入队
Status EnQueue(SqQueue &Q, QElemType e){if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;Q.base[Q.rear] = e;Q.rear = (Q.rear + 1) % MAXSIZE;return OK;
}
出队
Status DeQueue(SqQueue &Q, QElemType &e){if(Q.rear = Q.front) return ERROR;e = Q.base[Q.front];Q.front = (Q.front + 1) % MAXQSZIE;return OK;
}
取队头元素
SElemType GetHead(SqQueue Q){if(Q.rear = Q.front)return Q.base[Q.front];
}
链队
当无法估计长度时,则宜采用链队列
类型定义
#define MAXQSIZE 100
typedef struct Qnode{QElemType data;stuct Qnode *next;
}QNode,*QueuePtr;typedef struct{QueuePtr front;QueuePtr rear;
}LinkQueue;
初始化
Status lnitQueue(LinkQueue &Q){Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));if(!Q.front) exit(OVERFLOW);Q.front -> next = NULL;return OK;
}
销毁链队列
Status DestroyQueue(LinkQueue &Q){while(Q.front){p = Q.front -> next;free(Q.front);Q.front = p;}//Q.rear = Q.front -> next; free(Q.front); Q.front = Q.rear;return OK;
}
入队
Status EnQueue(LinkQueue &Q, QElemType e){p = (QueuePtr)malloc(sizeof(QNode));if(!p) exit(OVERFLOW);p -> data = 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;p = Q.front -> next;e = p -> data;Q.front -> next = p —> next;if(Q.rear == p) Q.rear = Q.front;delepe p;return OK;
}
求链队列的队头元素
Status GetHead(LinkQueue Q, QElemType &e){if(Q.front == Q.rear) return ERROR;e = Q.front -> next -> data;return OK;
}