队列和循环队列

本文介绍了两种循环队列的实现,一种是链表结构的循环队列,另一种是固定大小数组的循环队列。在链表结构中,详细展示了初始化、入队、出队和打印操作。对于数组循环队列,强调了在入队时要对头指针进行取余操作以避免溢出,同时展示了完整的添加、删除和输出过程。通过对队列操作的优化,实现了O(1)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.队列

        1老师的代码

#include <stdio.h>
#include <malloc.h>

typedef struct LinkNode{
    int data;
    struct LinkNode* next;
}*LinkNodePtr;

typedef struct LinkQuene{
    LinkNodePtr front;
    LinkNodePtr rear;
}*LinkQuenePtr;

LinkQuenePtr initQuene(){
    LinkQuenePtr resultPtr=(LinkQuenePtr)malloc(sizeof(struct LinkQuene));
    LinkNodePtr headerPtr=(LinkNodePtr)malloc(sizeof(struct LinkNode));
    headerPtr->next=NULL;

    resultPtr->front=headerPtr;
    resultPtr->rear=headerPtr;
    
    return resultPtr;
}

void outputLinkQuene(LinkQuenePtr paraQuenePtr){
    LinkNodePtr tempPtr=paraQuenePtr->front->next;
    while(tempPtr!=NULL){
        printf("%d",tempPtr->data);
        tempPtr=tempPtr->next;
    }
    printf("\r\n");
}

void enquene(LinkQuenePtr paraQuenePtr,int paraElement){
    LinkNodePtr tempNodePtr=(LinkNodePtr)malloc(sizeof(struct LinkNode));
    tempNodePtr->data=paraElement;
    tempNodePtr->next=NULL;

    paraQuenePtr->rear->next=tempNodePtr;

    paraQuenePtr->rear=tempNodePtr;
}

int dequene(LinkQuenePtr paraQuenePtr){
    int resultValue;
    LinkNodePtr tempNodePtr;

    if(paraQuenePtr->front==paraQuenePtr->rear){
        printf("The quene is empty\r\n");
        return -1;
    }

    tempNodePtr=paraQuenePtr->front->next;
    resultValue=tempNodePtr->data;
    paraQuenePtr->front->next=paraQuenePtr->front->next->next;

    if(paraQuenePtr->rear==tempNodePtr){
        paraQuenePtr->rear=paraQuenePtr->front;
    }

    free(tempNodePtr);
    tempNodePtr=NULL;

    return resultValue;
}


void testLinkQuene(){
    LinkQuenePtr tempQuenePtr;
    tempQuenePtr=initQuene();

    enquene(tempQuenePtr,10);
    enquene(tempQuenePtr,30);
    enquene(tempQuenePtr,50);

    outputLinkQuene(tempQuenePtr);

    printf("dequene gets %d\r\n",dequene(tempQuenePtr));
    printf("dequene gets %d\r\n",dequene(tempQuenePtr));
    printf("dequene gets %d\r\n",dequene(tempQuenePtr));
    printf("dequene gets %d\r\n",dequene(tempQuenePtr));

    enquene(tempQuenePtr,8);
    outputLinkQuene(tempQuenePtr);
}
int main(){
    testLinkQuene();
    return 1;
}

         运行结果

 

 2.自己的代码

        2.1结构体


typedef struct node{
	int data;
	struct node* next;
}*Nodeptr;

typedef struct quene{
	Nodeptr header;
	Nodeptr tail;
}*Queneptr;

        2.2初始化


Queneptr init(){
	Queneptr t=(Queneptr)malloc(sizeof(struct quene));
	Nodeptr q=(Nodeptr)malloc(sizeof(struct node));
	
    /*初始化头结点*/
	q->data=0;q->next=NULL;
	
    /*初始化队列*/
	t->header=q;
	t->tail=q;
	
	return t;
}

        2.3打印


void printQuene(Queneptr p){
	Nodeptr t=p->header->next;
	
    /*循环输出data*/
	while(t!=NULL){
		printf("%d ",t->data);
		t=t->next;
	}
	printf("\r\n");
}

       

        2.4添加.入队


void add(Queneptr p,int value){
    /*将数值存入*/
	Nodeptr t=(Nodeptr)malloc(sizeof(struct node));
	t->data=value;
	t->next=NULL;
	
    /*改变尾指针*/
	p->tail->next=t;
	p->tail=t;
}

     仅在队尾入队操作

 

          2.5删除.出队


int deletenode(Queneptr p){
	int value;
	Nodeptr t;
	
    /*判断表是否为空*/
	if(p->header==p->tail){
		printf("ERROR! empty\r\n");
		return -1;
	}
	
    /*取出队头值*/
	t=p->header->next;
	value=t->data;

    /*移动头指针*/
	p->header->next=t->next;
	
    /*若删除末尾结点,使尾指针与头指针相同*/
	if(p->tail==t)
		p->tail=p->header;
	
	free(t);
	t=NULL;
	
    /*返回队头值*/
	return value;
}

   仅在队头进行出队操作

 

            2.6测试


void test(){
    /*初始化*/
	Queneptr t=init();
	printf("初始化:\r\n");
	printQuene(t);
	
    /*添加测试*/
	printf("添加:\r\n");
	add(t,1);
	add(t,9);
	add(t,9);
	add(t,4);
	printQuene(t);
	printf("\n");
	
    /*删除测试*/
	printf("删除:\r\n");
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("\n");
	
	printf("再次添加:\r\n");
	add(t,19940221);
	printQuene(t);
}

        2.7完整代码

#include <stdio.h>
#include <malloc.h>

typedef struct node{
	int data;
	struct node* next;
}*Nodeptr;

typedef struct quene{
	Nodeptr header;
	Nodeptr tail;
}*Queneptr;

Queneptr init(){
	Queneptr t=(Queneptr)malloc(sizeof(struct quene));
	Nodeptr q=(Nodeptr)malloc(sizeof(struct node));
	
    /*初始化头结点*/
	q->data=0;q->next=NULL;
	
    /*初始化队列*/
	t->header=q;
	t->tail=q;
	
	return t;
}

void printQuene(Queneptr p){
	Nodeptr t=p->header->next;
	
    /*循环输出data*/
	while(t!=NULL){
		printf("%d ",t->data);
		t=t->next;
	}
	printf("\r\n");
}

void add(Queneptr p,int value){
    /*将数值存入*/
	Nodeptr t=(Nodeptr)malloc(sizeof(struct node));
	t->data=value;
	t->next=NULL;
	
    /*改变尾指针*/
	p->tail->next=t;
	p->tail=t;
}

int deletenode(Queneptr p){
	int value;
	Nodeptr t;
	
    /*判断表是否为空*/
	if(p->header==p->tail){
		printf("ERROR! empty\r\n");
		return -1;
	}
	
    /*取出队头值*/
	t=p->header->next;
	value=t->data;

    /*移动头指针*/
	p->header->next=t->next;
	
    /*若删除末尾结点,使尾指针与头指针相同*/
	if(p->tail==t)
		p->tail=p->header;
	
	free(t);
	t=NULL;
	
    /*返回队头值*/
	return value;
}

void test(){
    /*初始化*/
	Queneptr t=init();
	printf("初始化:\r\n");
	printQuene(t);
	
    /*添加测试*/
	printf("添加:\r\n");
	add(t,1);
	add(t,9);
	add(t,9);
	add(t,4);
	printQuene(t);
	printf("\n");
	
    /*删除测试*/
	printf("删除:\r\n");
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("delete %d\r\n",deletenode(t));
	printf("\n");
	
	printf("再次添加:\r\n");
	add(t,19940221);
	printQuene(t);
}

void main(){
	test();
}

        运行结果

 

二.循环队列

        1.老师的代码(小改动)

在入队操作时有点小错误,header的值也要取余,因为header递增,会超过给定长度

#include <stdio.h>
#include <malloc.h>

#define TOTAL_SPACE 5

typedef struct CircleIntQuene{
    int data[TOTAL_SPACE];
    int head;
    int tail;
}*CircleIntQuenePtr;

CircleIntQuenePtr initQuene(){
    CircleIntQuenePtr resultPtr=(CircleIntQuenePtr)malloc(sizeof(struct CircleIntQuene));
    resultPtr->head=0;
    resultPtr->tail=0;

    return resultPtr;
}

void enquene(CircleIntQuenePtr paraPtr,int paraValue){
    if((paraPtr->tail+1)%TOTAL_SPACE==((paraPtr->head)%TOTAL_SPACE)){
        printf("Quene full.\r\n");
        return;
    }

    paraPtr->data[paraPtr->tail%TOTAL_SPACE]=paraValue;
    paraPtr->tail++;
    printf("tail = %d\r\n",paraPtr->tail);
}

int dequene(CircleIntQuenePtr paraPtr){
    int resultValue;
    if(paraPtr->head==paraPtr->tail){
        printf("No element in the queen.\r\n");
        return -1;
    }

	printf("header = %d\r\n",paraPtr->head);
    resultValue=paraPtr->data[paraPtr->head%TOTAL_SPACE];
    paraPtr->head++;

    return resultValue;
}


void outputLinkQuene(CircleIntQuenePtr paraPtr){
    int i;
    if(paraPtr->head==paraPtr->tail){
        printf("Empty quene.\r\n");
        return ;
    }
    
    printf("Element in the quene:");
    for(i=paraPtr->head;i<paraPtr->tail;++i){
        printf("%d, ",paraPtr->data[i%TOTAL_SPACE]);
    }
    printf("\r\n");
}

void testLinkQuene(){
    int i=10;
    CircleIntQuenePtr tempPtr=initQuene();
    for(;i<16;i++){
        enquene(tempPtr,i);
    }

    outputLinkQuene(tempPtr);

    for(i=0;i<6;i++){
        printf("dequene gets %d\r\n",dequene(tempPtr));
    }

    enquene(tempPtr,8);
    enquene(tempPtr,1);
    enquene(tempPtr,9);
    enquene(tempPtr,9);
    enquene(tempPtr,4);
    
    outputLinkQuene(tempPtr);
    
    dequene(tempPtr);
    dequene(tempPtr);
    dequene(tempPtr);
    dequene(tempPtr);
    printf("AFTER DELETE :\r\n");
    outputLinkQuene(tempPtr);
    
    printf("SECOND \r\n");
    enquene(tempPtr,8);
    enquene(tempPtr,1);
    enquene(tempPtr,9);
    enquene(tempPtr,9);
    enquene(tempPtr,4);
    
    
    outputLinkQuene(tempPtr);
    
}

int main(){
    testLinkQuene();
    return 1;
}

未改的运行结果,可以看到第二次添加时溢出了

令header也取余,运行结果正确

 

 

2.自己的代码

        2.1结构体


typedef struct Circlequene{
	int data[LENGTH];
	int header;
	int tail;
}*Cqueneptr;

        2.2初始化


Cqueneptr init(){
	Cqueneptr t=(Cqueneptr)malloc(sizeof(struct Circlequene));

	t->header=0;
	t->tail=0;
	
	return t;
}

        2.3打印


void printQuene(Cqueneptr p){
    /*判断是否为空*/
    if(p->header==p->tail){
    	printf("\r\n");
        return ;
    } 
    
    printf("打印:");
    int i;

    /*循环打印data值*/
    for(i=p->header;i<p->tail;++i){
        printf("%d ",p->data[i%LENGTH]);
    }
    printf("\r\n");
}

        2.4入队


void add(Cqueneptr p,int Value){
    /*判断是否已满*/
    /*header也要取余,因为header也是递增的,会超过LENGTH*/
    if((p->tail+1)%LENGTH==((p->header)%LENGTH)){
        printf("ERROR! 已满\r\n");
        return;
    }

    /*将值存入*/
    p->data[p->tail%LENGTH]=Value;
    p->tail++;
    printf("tail = %d\r\n",p->tail);
}

       第一步:逐个入队,4加入后tail为4,此时判断队列已满

 第二步:逐个删除,header为4,与tail相等,此时判断队列已空

 第三步:再次加入,tail值递增,在2号位加入7后,tail值为8,再次判断队列已满,此时若再次出队操作,header也会为8,超过了LENGTH=5,因此header也应取余

 

         2.5出队


int deleteC(Cqueneptr p){
    /*判断是否为空*/
    if(p->header==p->tail){
        printf("ERROR! 空表\r\n");
        return -1;
    }

    /*取出队头值,并改变头指针*/
	printf("header = %d\r\n",p->header);
	int result;
    result=p->data[p->header%LENGTH];
    p->header++;

    return result;
}

        2.6测试


void test(){
    /*初始化*/
	Cqueneptr t=init();
	printf("初始化:\r\n");
	printQuene(t);
	
    /*添加测试*/
	printf("添加:\r\n");
	add(t,1);
	add(t,9);
	add(t,9);
	add(t,4);
	add(t,2);
	printQuene(t);
	printf("\n");
	
    /*删除测试*/
	printf("删除:\r\n");
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("\n");
	
    /*再次添加,检查header超过LENGTH后,是否出现异常*/
	printf("再次添加:\r\n");
	add(t,0);
	add(t,7);
	add(t,1);
	add(t,7);
	add(t,10);
	printf("删除后:\r\n");
	printQuene(t);
	
	printf("删除 2 :\r\n");
	deleteC(t);
	printQuene(t);
}

        2.7完整代码

#include <stdio.h>
#include <malloc.h>

#define LENGTH 5
typedef struct Circlequene{
	int data[LENGTH];
	int header;
	int tail;
}*Cqueneptr;


Cqueneptr init(){
	Cqueneptr t=(Cqueneptr)malloc(sizeof(struct Circlequene));

	t->header=0;
	t->tail=0;
	
	return t;
}

void printQuene(Cqueneptr p){
    /*判断是否为空*/
    if(p->header==p->tail){
    	printf("\r\n");
        return ;
    } 
    
    printf("打印:");
    int i;

    /*循环打印data值*/
    for(i=p->header;i<p->tail;++i){
        printf("%d ",p->data[i%LENGTH]);
    }
    printf("\r\n");
}

void add(Cqueneptr p,int Value){
    /*判断是否已满*/
    /*header也要取余,因为header也是递增的,会超过LENGTH*/
    if((p->tail+1)%LENGTH==((p->header)%LENGTH)){
        printf("ERROR! 已满\r\n");
        return;
    }

    /*将值存入*/
    p->data[p->tail%LENGTH]=Value;
    p->tail++;
    printf("tail = %d\r\n",p->tail);
}

int deleteC(Cqueneptr p){
    /*判断是否为空*/
    if(p->header==p->tail){
        printf("ERROR! 空表\r\n");
        return -1;
    }

    /*取出队头值,并改变头指针*/
	printf("header = %d\r\n",p->header);
	int result;
    result=p->data[p->header%LENGTH];
    p->header++;

    return result;
}

void test(){
    /*初始化*/
	Cqueneptr t=init();
	printf("初始化:\r\n");
	printQuene(t);
	
    /*添加测试*/
	printf("添加:\r\n");
	add(t,1);
	add(t,9);
	add(t,9);
	add(t,4);
	add(t,2);
	printQuene(t);
	printf("\n");
	
    /*删除测试*/
	printf("删除:\r\n");
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("delete %d\r\n",deleteC(t));
	printf("\n");
	
    /*再次添加,检查header超过LENGTH后,是否出现异常*/
	printf("再次添加:\r\n");
	add(t,0);
	add(t,7);
	add(t,1);
	add(t,7);
	add(t,10);
	printf("删除后:\r\n");
	printQuene(t);
	
	printf("删除 2 :\r\n");
	deleteC(t);
	printQuene(t);
}

void main(){
	test();
}

        运行结果

初始化:

添加:
tail = 1
tail = 2
tail = 3
tail = 4
ERROR! 已满
打印:1 9 9 4

删除:
header = 0
delete 1
header = 1
delete 9
header = 2
delete 9
header = 3
delete 4
ERROR! 空表
delete -1

再次添加:
tail = 5
tail = 6
tail = 7
tail = 8
ERROR! 已满
删除后:
打印:0 7 1 7
删除 2 :
header = 4
打印:7 1 7

队列仅仅在队首,对尾进行出队,入队操作,因此怎加和删除的时间复杂度都是O(1),并且有先进先出的特点。

循环队列则是通过下标的巧妙运算,充分利用空间,形成逻辑上的环。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值