C语言--栈与队列3(循环队列)

一、顺序队列的操作(明确顺序队列中会故意少用一个元素的空间)

0)定义---循环队列的定义和一些宏定义

#include 
#include 
#define ElementType int//如果要修改变量类型,只需修改这里的宏定义,入队出队的printf和主函数的printf即可,因为这个代码是初学顺序队的操作
#define MaxSize 4   //明确循环队列少用了一个元素空间,实际上存放的是MaxSize-1个元素
#define LEN sizeof(SqQueue)
//循环队列,少用一个元素空间
typedef struct{
    ElementType* Base;
    int Head;//队头元素的下标
    int Back;//队尾元素的下标
}SqQueue;

1)初始化---动态开辟一段连续的内存,并让队头队尾元素的下标为0

//初始化顺序队
void Init_SqQueue(SqQueue* queue){
    queue->Base=(ElementType*)malloc(MaxSize*LEN);
    if(queue->Base==NULL){
        printf("初始化顺序队失败!\n");
        exit(0);
    }
    else{
        queue->Head=queue->Back=0;
        printf("初始化顺序队成功!\n");
    }
}

2)计算长度---注意到队头的下标不一定就是小于队尾的下标,队头的下标也不一定一直为0

//计算顺序队长度
int SqQueue_Length(SqQueue queue){
    int length=(queue.Back-queue.Head+MaxSize)%MaxSize;
    return length;
}

3)入队---队尾插入,时时刻刻判断队列是否满了,并打印一些信息验证是否入队正常

注意到判断是否队满代码:(queue->Back+1)%MaxSize==queue->Head

注意到入队的操作代码:queue->Base[queue->Back]=data;

注意到入队后队尾的下标偏移代码:queue->Back=(queue->Back+1)%MaxSize;

//入队--队尾插入,判断是否为满
void Enter_SqQueue(SqQueue* queue,ElementType data){
    if((queue->Back+1)%MaxSize==queue->Head){
        printf("入队失败,队已满!\n");
    }
    else{
        queue->Base[queue->Back]=data;
        printf("%d元素入队第%d位置成功!\n",queue->Base[queue->Back],queue->Back);
        queue->Back=(queue->Back+1)%MaxSize;   
        printf("此时队尾元素下标是:%d\n",queue->Back);
    }
}

4)出队---对头删除,时时刻刻判断队是否为空,并打印一些信息验证是否出队正常

注意到判断是否为空队代码:queue->Head==queue->Back

注意到出队操作代码:*data=queue->Base[queue->Head];

注意到对头的下标偏移代码:queue->Head=(queue->Head+1)%MaxSize;

//出队--对头删除。判断是否为空
void Out_SqQueue(SqQueue* queue,ElementType* data){
    if(queue->Head==queue->Back){
        printf("出队失败,队已空!\n");
    }
    else{
        *data=queue->Base[queue->Head];
        printf("第%d位置%d元素出队成功!\n",queue->Head,queue->Base[queue->Head]);
        queue->Head=(queue->Head+1)%MaxSize;
        printf("此时队头元素下标是:%d\n",queue->Head);
    }
}

5)销毁队--释放内存后重新赋值结构体的成员,在下一次入队时要先进行初始化操作

//销毁队
void Destroy_SqQueue(SqQueue* queue){
    free(queue->Base);
    queue->Base=NULL;
    queue->Head=queue->Back=0;
    if(SqQueue_Length(*queue)==0){
        printf("销毁成功!\n");
    }
    else{
        printf("销毁失败!\n");
    }
}

6)取对头元素---前提是队不能为空

注意到取队头元素的代码:return queue.Base[queue.Head];

//取对头元素
ElementType Get_SqQueue_Head(SqQueue queue){
    if(queue.Head==queue.Back){
        printf("队尾空,无法取对头元素!\n");
    }
    else{
        return queue.Base[queue.Head];
    }
}

二、实践

创建结构体变量

初始化顺序队

3次入队---此时不会出现队满而入队失败

计算当前长度

1次出队

计算当前长度

显示对头元素

销毁对

显示对头元素

再次初始化--为了第二次入队

4次入队---会出现队满入队失败的情况

计算当前长度

4次出队---会出现对空出队失败的情况

计算当前长度

#include 
#include 
#define ElementType int
#define MaxSize 4   //明确循环队列少用了一个元素空间,实际上存放的是MaxSize-1个元素
#define LEN sizeof(SqQueue)
//循环队列,少用一个元素空间
typedef struct{
    ElementType* Base;
    int Head;
    int Back;
}SqQueue;
//初始化顺序队
void Init_SqQueue(SqQueue* queue){
    queue->Base=(ElementType*)malloc(MaxSize*LEN);
    if(queue->Base==NULL){
        printf("初始化顺序队失败!\n");
        exit(0);
    }
    else{
        queue->Head=queue->Back=0;
        printf("初始化顺序队成功!\n");
    }
}
//计算顺序队长度
int SqQueue_Length(SqQueue queue){
    int length=(queue.Back-queue.Head+MaxSize)%MaxSize;
    return length;
}
//入队--队尾插入,判断是否为满
void Enter_SqQueue(SqQueue* queue,ElementType data){
    if((queue->Back+1)%MaxSize==queue->Head){
        printf("入队失败,队已满!\n");
    }
    else{
        queue->Base[queue->Back]=data;/?????/???????????????????????
        printf("%d元素入队第%d位置成功!\n",queue->Base[queue->Back],queue->Back);
        queue->Back=(queue->Back+1)%MaxSize;   
        printf("此时队尾元素下标是:%d\n",queue->Back);
    }
}
//出队--对头删除。判断是否为空
void Out_SqQueue(SqQueue* queue,ElementType* data){
    if(queue->Head==queue->Back){
        printf("出队失败,队已空!\n");
    }
    else{
        *data=queue->Base[queue->Head];/??????????????????????????????
        printf("第%d位置%d元素出队成功!\n",queue->Head,queue->Base[queue->Head]);
        queue->Head=(queue->Head+1)%MaxSize;
        printf("此时队头元素下标是:%d\n",queue->Head);
    }
}
//销毁队
void Destroy_SqQueue(SqQueue* queue){
    free(queue->Base);
    queue->Base=NULL;
    queue->Head=queue->Back=0;
    if(SqQueue_Length(*queue)==0){
        printf("销毁成功!\n");
    }
    else{
        printf("销毁失败!\n");
    }
}
//取对头元素
ElementType Get_SqQueue_Head(SqQueue queue){
    if(queue.Head==queue.Back){
        printf("队尾空,无法取对头元素!\n");
    }
    else{
        return queue.Base[queue.Head];
    }
}
int main(){
    SqQueue queue;
    ElementType data;
    //初始化
    Init_SqQueue(&queue);
    printf("\n");
    //入队
    Enter_SqQueue(&queue,111);
    Enter_SqQueue(&queue,222);
    Enter_SqQueue(&queue,333);
    //计算当前长度
    printf("\n长度为%d\n\n",SqQueue_Length(queue));
    //出队
    Out_SqQueue(&queue,&data);
    //计算当前长度
    printf("\n长度为%d\n\n",SqQueue_Length(queue));
    //取对头元素
    printf("对头元素是%d\n",Get_SqQueue_Head(queue));
    printf("\n");
    //销毁队
    Destroy_SqQueue(&queue);
    //计算当前长度
    printf("\n长度为%d\n\n",SqQueue_Length(queue));

    printf("\n");

    //销毁后再次初始化
    Init_SqQueue(&queue);
    printf("\n");
    //再次入队--故意多一次入队
    Enter_SqQueue(&queue,444);
    Enter_SqQueue(&queue,555);
    Enter_SqQueue(&queue,666);
    Enter_SqQueue(&queue,777);
    //计算当前长度
    printf("\n长度为%d\n\n",SqQueue_Length(queue));
    //再次出队--故意多一次出队
    Out_SqQueue(&queue,&data);
    Out_SqQueue(&queue,&data);
    Out_SqQueue(&queue,&data);
    Out_SqQueue(&queue,&data);
    //计算当前长度
    printf("\n长度为%d\n",SqQueue_Length(queue));

    return 0;
}

你可能感兴趣的:(C语言--栈与队列,c语言,开发语言)