1、栈的顺序存储
//-----栈的顺序存储表示------
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
2、基本操作
//------基本操作-----------
Status InitStack(SqStack *S){
//构造一个空栈
(*S).base =(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!(*S).base) exit(OVERFLOW);
(*S).top =(*S).base;
(*S).stacksize =STACK_INIT_SIZE;
return OK;
}
//2
Status DestroyStack(SqStack *S){
//销毁一个栈
free( (*S).base);//释放表
(*S).top =NULL;
(*S).base =NULL;
(*S).stacksize =0;
return OK;
}
//3,
Status ClearStack(SqStack *S){
//设置表为空
(*S).top =(*S).base;//指向栈底
return OK;
}
//4
Status StackEmpty(SqStack S){
//是否为空
if(S.top == S.base)
return TRUE;
else
return FALSE;
}
//5
int StackLength(SqStack S){
//返回栈的长度
return S.top-S.base;
}
//6
Status GetTop(SqStack S,SElemType *e){
//如栈不空,返回栈顶元素
if(S.top == S.base)
return ERROR;
*e =*(S.top-1); //返回栈顶元素
return OK;
}
//7
Status Push(SqStack *S,SElemType e){
//入栈操作
//判断栈满
if( (*S).top-(*S).base >(*S).stacksize){
(*S).base =(SElemType *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!(*S).base) exit(OVERFLOW);
(*S).top =(*S).base+(*S).stacksize;//重新定位栈顶指针
(*S).stacksize+=STACKINCREMENT;
}
*( (*S).top )++ =e; //先插入,栈顶指针在+1
return OK;
}
//8
Status Pop(SqStack *S,SElemType *e){
//出栈操作
//判断是否为空
if((*S).top ==(*S).base) return ERROR;
*e= *--(*S).top;//先栈顶指针-1,在取元素
return OK;
}
//9
Status StackTraverse(SqStack S,Status(*visit)(SElemType))
{ // 从栈底到栈顶依次对栈中每个元素调用函数visit()
while(S.top>S.base)
visit(*S.base++);
printf("\n");
return OK;
}
3、队列的链式存储结构
//-----单链队列---队列的链式存储结构
typedef struct QNode{
QElemType data;
struct QNode *next;
}QNode, *QueuePtr;
typedef struct {
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;
4、基本操作代码
//--------基本操作-----
//1
Status InitQueue(LinkQueue *Q){
//构造一个空队列
(*Q).front =(QueuePtr)malloc(sizeof(QNode));//生成头结点
if(!(*Q).front) exit(OVERFLOW);
(*Q).front->next =NULL; //头结点的指针域指向空
(*Q).rear =(*Q).front;
return OK;
}
//2
Status DestroyQueue(LinkQueue *Q){
//销毁一个队列
while((*Q).front){ //从队头释放资源
(*Q).rear =(*Q).front->next;
free( (*Q).front);
(*Q).front =(*Q).rear;
}
return OK;
}
//3
Status ClearQueue(LinkQueue *Q){
QueuePtr p,q;
p =(*Q).front->next; //指向队列的第一个结点
while(p){ //从第一个结点释放资源
q =p->next;
free( p);
p =q;
}
(*Q).front->next=NULL;
(*Q).rear =(*Q).front;//为空的条件
return OK;
}
//4
Status QueueEmpty(LinkQueue Q){
if(Q.front == Q.rear)
return OK;
else
return ERROR;
}
//5
int QueueLength(LinkQueue Q){
int j=0;
QueuePtr p =Q.front;
while(p !=Q.rear){ //从队头直到和队尾相同时结束
j++;
p =p->next;
}
return j;
}
//6
Status GetHead(LinkQueue Q,QElemType *e){
//返回队头元素
QueuePtr p;
//判断不为空
if(Q.front == Q.rear)
return ERROR;
p =Q.front->next;
*e =p->data;
return OK;
}
//7
/*
算法思想:
1,开辟一个新结点p,为新结点的数据域和指针域分别赋值
2,将新结p链接到队尾后,即把队尾结点的指针域指向新的结点p
3,将尾指针指向p
*/
Status EnQueue(LinkQueue *Q,QElemType e){
//插入元素
QueuePtr p=(QueuePtr)malloc(sizeof(QNode)); //申请结点
if(!p)
exit(OVERFLOW);
p->data=e;
p->next=NULL;
//在队尾插入
(*Q).rear->next=p;
(*Q).rear=p;
return OK;
}
//8,
/*
算法思想:
1,判断队列不为空
2,使待删除p指向队头的第一个结点,在删除前还需要保存该结点的信息。
3,根据队列的操作逻辑定义,把队头结点的指针域指向p的下一个结点。
4,判断待删除p是否指向了队尾结点,如果指向了队尾,则把队尾指针指向队头指针
*/
Status DeQueue(LinkQueue *Q,QElemType *e){
QueuePtr p;
if((*Q).front ==(*Q).rear) return ERROR;
p =(*Q).front->next;//待删除结点p
*e =p->data;
(*Q).front->next =p->next;
if((*Q).rear ==p){//特殊判断,当待删除的结点是最后一个时,需要特殊处理。
(*Q).rear =(*Q).front;
}
free(p);
return OK;
}
Status QueueTraverse(LinkQueue Q,void(*vi)(QElemType))
{
QueuePtr p;
p=Q.front->next;
while(p)
{
vi(p->data);
p=p->next;
}
printf("\n");
return OK;
}
5、非循环队列的顺序存储结构之一
#define QUEUE_INIT_SIZE 10 //初始分配量
#define QUEUE_INCREMENT 5 //分配增量
typedef struct {
QElemType *base; //初始化时动态分配的存储空间
int rear; //尾指针,队列不为空时,指向数组元素下一个位置(存放的是数组的下标)
int queuesize; //当前分配的空间大小
}SQueue;
6、非循环队列的顺序存储结构之二
#define QUEUE_INIT_SIZE 10 //初始分配量
#define QUEUE_INCREMENT 5 //分配增量
typedef struct {
QElemType *base; //初始化时动态分配的存储空间
int front; //头指针,若队列不为空只想队头元素。
int rear; //尾指针,队列不为空时,指向数组元素下一个位置(存放的是数组的下标)
int queuesize; //当前分配的空间大小
}SQueue;
7、使用循环队列
#define MAXQSIZE 100 // 最大队列长度
typedef struct
{
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;
8、循环队列的顺序结构基本操作
//--------循环队列的基本操作----------
//1,初始化一个队列
Status InitQueue(SqQueue *Q)
{
(*Q).base =(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
if(!(*Q).base) exit(OVERFLOW);
(*Q).front =(*Q).rear =0;
return OK;
}
//2销毁
Status DestroyQueue(SqQueue *Q)
{
if((*Q).base)
free((*Q).base);
(*Q).front =(*Q).rear=0;
(*Q).base =NULL;
return OK;
}
//3清空
Status ClearQueue(SqQueue *Q)
{
(*Q).front =(*Q).rear =0;
return OK;
}
//4是否为空
Status QueueEmpty(SqQueue Q){
if( Q.rear ==Q.front)
return TRUE;
else
return FALSE;
}
//5队列的长度
int QueueLength(SqQueue Q)
{
return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
}
//6获取队头元素
Status GetHead(SqQueue Q,QElemType *e)
{
//判断不为空,这里舍弃一个空间
if( Q.rear ==Q.front)
return ERROR;
*e =Q.base[Q.front];
return OK;
}
//7插入操作
/*
算法思想:
1,判断队列不为满,(Q.rear+1)%MAXQSIZE ==Q.front
2,在队尾插入新元素
3,队尾指针加1
*/
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)%MAXQSIZE;
return OK;
}
//8删除操作
/*
算法思想:
1,先判断循环队列不为空。
2,删除队头指针的数据元素,在此之前保存待删除元素的信息。
3,队头指针加1。
*/
Status DeQueue(SqQueue *Q,QElemType *e)
{
if((*Q).rear ==(*Q).front)
return ERROR;
*e =(*Q).base[(*Q).front];
(*Q).front =((*Q).front+1)%MAXQSIZE;
return OK;
}
//9输出
Status QueueTraverse(SqQueue Q,void(*visit)(QElemType))
{
int i;
i =Q.front;
while(i!=Q.rear){
(*visit)( Q.base[i] );
i=(i+1)%MAXQSIZE;
}
printf("\n");
return OK;
}