首页 > 其他分享 >数据结构C语言版_队列笔记||已测试所有代码均可运行

数据结构C语言版_队列笔记||已测试所有代码均可运行

时间:2024-10-23 20:16:53浏览次数:3  
标签:结点 队列 C语言 printf front 数据结构 rear 指针

队列

源文件使用markdown编写,CSDN文章发布好像有部分语法改变。每一部分我都有加一个返回标题好像不能使用了。但是CSDN自带一个目录总结,你们无视掉我写的目录直接用CSDN的吧。
总结笔记不易,如果有帮助到你希望点个赞。

所有代码均已在VScode中运行过,部分代码块因为格式原因没有高亮。
全部代码展示在最后,可以直接复制运行,部分代码被注释了需要你手动删除注释符号。

普通队列与循环队列:
结构体
初始化队列
判断队空
入队
出队
检查队满
循环队列

链式队列:
链式队列
链式队列结构
初始化
判断是否为空
入队
出队
遍历
全部代码展示

结构体

typedef int ElemType;
#define MaxSize 10
typedef struct{
	ElemType data[MaxSize];   
	//用静态数组存放队列元素
	int front,rear;           
	//定义队头指针和队尾指针
}SqQueue;
//Sq-----sequence顺序

  • 队头指针front————指向队头元素

  • 队尾指针rear————指向队尾元素的后一个位置(下一个应该插入的位置)

    返回标题

初始化队列

我是队data[3]←我是rear指针
我是队data[2]
我是队data[1]
我是队data[0]←我是front指针
//函数功能:初始化队列
void InitQueue(SqQueue *Q){
	//初始时,队头和队尾指针都指向0;
	Q->rear=Q->front=0;
}

void testQueue(){
	SqQueue Q;     //声明一个队列(顺序存储)————这段语句执行后,
	//就会在内存中分配连续大小为MaxSize*sizeof(ElemType)的空间
}

初始化时↓

我是front指针→data[0]我是队←我是rear指针
font和rear指向同一个地方。

返回标题

判断队空

#include <stdbool.h>
#define MaxSize 10
typedf struct{
	Elemtype data[MaxSize];   
	//用静态数组存放队列元素
	int front,rear;           
	//定义队头指针和队尾指针
}SqQueue;
//Sq-----sequence顺序

//函数功能:判断队列是否为空
bool QueueEmpty(SqQueue Q){
	if(Q.rear==Q.front)  //队空的条件
		return true;
	else
		return false;
}

该函数判断了队头指针和队尾指针是否相同,从而来判断队是否为空,然鹅这是有局限性的。我们稍后会再解释。
返回标题

入队

#define MaxSize 10
typedf struct{
	Elemtype data[MaxSize];   //用静态数组存放队列元素
	int front,rear;           //定义队头指针和队尾指针
}SqQueue;
//Sq-----sequence顺序

//函数功能:入队
void EnQueue(SqQueue* Q,ElemType x){

    if(QueueEmpty(*Q))

        return false;//报错

    Q->data[Q->rear]=x;  //将x插入到队尾

    Q->rear=Q->rear+1;  // 队尾指针后移

    printf("%d",&x);

}

向Enqueue传入队的位置和新元素,判断一下队是否可入。如果可入就将新元素入队。新元素放进队尾指针指向的位置,再让队尾指针指向向后面挪一位。

我想进来
我是front指针→data[0]我是队←我是rear指针

进入:

←我是rear指针
我是front指针→data[0]我进来了

检查队满

我们能不能用Q . r e a r = = MaxSize作为队列满的条件呢?
答:肯定是不能。
————————————————

分析原因:假设我们通过入队操纵使得队列满使得Q .rear = = M a x S i z e,但是由于我们出队操作的过程中,队尾指针不会改变,一直保持Q . r e a r = = M a x S i z e MaxSize,而我们的队头指针front一直在变化,就是在这种情况下导致队列不满,但Q . r e a r = = M a x S i z e。所以Q . r e a r = = M a x S i z e 不能作为队列满的判断条件。
————————————————

简单来说,就是会出现队头队尾都指向maxSize的情况,这样就无法判断队列到底是为空还是满了。

那么如何判断队满呢?我们可以继续看循环队列。
返回标题

循环队列

循环队列与取模运算


//函数功能:入队
bool EnQueue(SqQueue &Q,ElemType x){
	if(队列已满)
		return false;//报错
	Q.data[Q.rear]=x;  //将x插入到队尾
	Q.rear=(Q.rear+1)%MaxSize;  // 队尾指针加一取模
	//这个语句的操作,
	//使得Q.rear的取值范围固定在了{0,1,2,3,...,MaxSize-1}。
	//可以理解将存储空间变成了“环状”。
	return ture;
}

假设队伍容量为5;
1%5=1;2%5=2;3%5=3;
4%5=4;5%5=0;6%5=1;
余数一直在0-4之间循环。使得存储空间和范围变成了环状。

这样我们可以以循环队列的队尾指针的下一个位置是队头来判断是否队满。
但是我们rear指针所指的空间不能使用,因为添加了数据之后,rear会往后挪一格,从而与队头指针重合,队空队满的条件再次一致。

判断队满:

bool  QueueFull(SqQueue* Q){

    if((Q->rear+1)%MaxSize==Q->front)//判断队空或满
        { 
          printf("队满\n");
            return false;}
            //报错
        else
        {printf("队未满\n");
        return true ;}
}
//函数功能:判断队列是否为空
bool QueueEmpty(SqQueue Q){
	if(Q.rear==Q.front)  //队空的条件
		return true;
	else
		return false;
}
//函数功能:入队
bool EnQueue(SqQueue*Q,
			 ElemType x){
    //if(队列已满)
    if((Q->rear+1)%MaxSize==Q->front)//判断队空或满
        return false;//报错
    Q->data[Q->rear]=x;  
    //将x插入到队尾
    Q->rear=(Q->rear+1)%MaxSize;  // 队尾指针加一取模
    //这个语句的操作,使得Q.rear的取值范围固定在了{0,1,2,3,...,MaxSize-1}。
    //可以理解将存储空间变成了“环状”。
    printf("入队元素为%d\n",x);
    return true;
}

返回标题

循环队列出队

//函数功能:出队——删除一个队头元素,并用x返回
bool DeQueue(SqQueue *Q,ElemType x){
    if(Q->rear==Q->front)
        return false;
        //队列为空,报错
    x=Q->data[Q->front];
    //队头元素赋值给x;
    Q->front=((Q->front+1)%MaxSize);
    printf("出队已完成,出队元素为%d\n",x);
    //队头指针加一取模保证在循环队列中队头指针后移;
    return true;
}

该函数传入一个队的位置,和一个

循环队列的出队操作类似于顺序表的删除操作,但不同的是队列只能让队头先出队。

  • SqQueue &Q:这是对循环队列对象的引用。通过引用传递,可以直接修改传入的队列对象而无需复制整个队列,提高了效率。
  • ElemType &x:用于存储出队元素的引用参数。出队成功后,队头元素的值将被赋给这个参数。

注意,该函数使用之后只是将一个元素出队,出队的元素可以储存在x中方便我们输出。
返回标题

循环队列中查找元素

//函数功能:获得队头元素的值,用x返回。
bool GetHead(SqQueue *Q,ElemType x){
    if(Q->rear==Q->front){
        printf("队为空,无法出队");
        return false;
        }
        else {//队空,无元素,报错;
    x=Q->data[Q->front];
    printf("队头为%d\n",x);
    return true;}
}

可以发现上述代码与出队操作类似。同样的x这里起到的作用是方便我们获取找到的元素。
与出队相比,这里仅仅获取元素,并没有将元素删除。
返回标题

**真正的查找元素

bool searchInCircularQueue(SqQueue*q,int target) {
    int index = q->front;
    while (index!= q->rear) {
        if (q->data[index] == target) {
            return true;
        }
        index = (index + 1) % MaxSize;
    }
        return false;
        }
void  FindElement(SqQueue*q,int target){
   if
   (searchInCircularQueue(q, target)==true) {
        printf("%d 元素在该队列中.\n", target);
    } else {
        printf("%d 元素不在该队列中.\n", target);
    }
}

返回标题

一、函数功能

这个函数的目的是在给定的循环队列中查找特定的目标元素。如果目标元素存在于队列中,则返回true;否则,返回false

二、参数说明

  • SqQueue * q:这是一个指向循环队列结构体的指针。通过这个指针,可以访问循环队列的各个成员,包括存储数据的数组、队头指针front和队尾指针rear
  • int target:要在队列中查找的目标元素值。

三、代码逻辑分析

  1. int index = q->front;
    • 初始化一个索引变量index,将其设置为队头指针的值。这个索引将用于遍历循环队列中的元素。
  2. while (index!= q->rear) {... }
    • 这是一个循环,只要索引不等于队尾指针,就会继续执行循环体。这个条件确保在遍历队列时不会超出队列的范围。
  3. if (q->data[index] == target) { return true; }
    • 在循环体内,首先检查当前索引位置的元素是否等于目标元素。如果相等,说明找到了目标元素,立即返回true
  4. index = (index + 1) % MAX_SIZE;
    • 如果当前元素不等于目标元素,将索引向后移动一位。由于是循环队列,需要使用取模运算% MAX_SIZE来确保索引始终在合法的范围内。当索引达到数组的末尾时,取模运算会将其重新设置为数组的开头,实现循环遍历。
  5. return false;
    • 如果循环结束后还没有找到目标元素,说明目标元素不在队列中,返回false

返回标题

其他的思路

关于循环队列队满与队空的区分与判断,还有其他的处理方式。

  1. 刚刚所述的方法,代价是浪费一个存储单元。
  2. 在定义类型中,定义一个数据类型成员size,标示元素个数。初始化时,rear=front=0;size=0;队空的条件是Q。Size= =0;队满:Q.size = = MaxSize;判断条件从头尾指针变成了size。
#define MaxSize 10
typedf struct{
	Elemtype data[MaxSize];  
	 //用静态数组存放队列元素
	int front,rear;           
	//定义队头指针和队尾指针
	int size;                
	 //队列当前长度
}SqQueue;
//插入成功,入队,size++;
//删除成功,出队,size--;
  1. 在结构体中增加一个tag,用于区分队空与队满;出队成功时tag=0;入队成功时tag=1;而入队是不会使队为空的,只有出队会使队为空。所以我们可以判断font= =rear时增加一个判断tag=0还是tag=1来判断队空还是队满。
front = =rear&&tag==1;//队满
front=  =rear&&tag==0;//队空

返回标题

遍历输出

void printCircularQueue(SqQueue*q) {
    if (QueueEmpty(*q)) {
        printf("Queue is empty.\n");
        return;
    }
    int index = q->front;
    while (index!= q->rear) {
        printf("%d ", q->data[index]);
        index = (index + 1) % MaxSize;
    }
    printf("\n");
}

返回标题

链式队列

返回标题

链队列结构

***一个同时带有队头指针和队尾指针的单链表。头指针指向队头节点,尾指针指向队尾节点。
因为他同时带有队的性质和链表的性质,因此链式存储队列可以分为:带头节点的队列,和不带头结点的队列。

带头结点:

head–>我是队员–>我是队员–>我是队员–>NULL

front

rear
不带头结点:
我是队员–>我是队员–>我是队员–>NULL

front

rear
typedef struct LinkNode{     
//链式队列结点
	ElemType data;
	struct LinkNode *next;
}LinkNode;  

typedef struct LinkQueue{               
//链式队列
	LinkNode *front,*rear;   
	//队列的队头和队尾指针
}LinkQueue;

LinkNode表示链式队列中的节点;
Link Queue则表示整个链式队列。

返回标题

初始化

带头结点的初始化
//函数功能:初始化队列--带头结点
void InitLinkQueue (LinkQueue *Q){
    //初始化时,frony 和rear指针都指向头结点
    Q->front=Q->rear =(LinkNode*)malloc(sizeof(LinkNode));
    Q->front->next=NULL;
    printf("已初始化一个链式队列");
}
head→NULL
↑ ↑
front rear
head→我是队员→我是队员→我是队员→NULL

front

rear
不带头结点的初始化
void InitLinkNoHeadQueue (LinkQueue *Q){
     //初始化时,frony 和rear指针都指向NULL
    Q->front = Q->rear = NULL;
    printf("一个不带头节点的链式队列已初始化完毕");

}

返回标题

判断是否为空

带头结点:
head->NULL
↑ ↑
front rear
//判断队列是否为空
bool LinkIsEmpty(LinkQueue *Q){
    if(Q->front==Q->rear)
     //其实,只有为空时,Q.front==Q.rear,其他条件也没必要考虑了。
        {printf("该链式队列为空\n");
            return true;
        }
    else{
        printf("该链式队列不为空\n");.
        return false;
        }
}
不带头结点
NULL
↑ ↑
front rear
//判断队列是否为空
boolean IsEmpty(LinkQueue Q){
	if(Q.front==NULL)  //
		return true;
	else
		return false;
}

返回标题

链式队列入队

带头结点
//函数功能:带头结点队列新元素入队--带头结点

void EnLinkQueue(LinkQueue *Q,ElemType x){
    LinkNode *newNode =(LinkNode*)malloc(sizeof(LinkNode));//申请一个结点newNode
    newNode->data=x;
    newNode->next=NULL;
    Q->rear->next=newNode;
    //新结点插入到rear之后
    Q->rear=newNode;    
    // 修改表尾指针,入队操作不需要需要表头指针front;
    printf("%d已入队\n",x);
}

传入链式队的位置和新元素给该函数;他会开辟一个空间,将传入的x放入该空间的data 部分,next指向null。队尾rear指向该空间。

我想进来
head->NULL
↑ ↑
front rear

进来:

head->我是空间sNULL
[ date ] * next我也是空间s

front rear
我是空间s
head->我进来了->NULL
[ date ] * next[ date ] * next

front

rear
不带头结点
//函数功能:带头结点队列新元素入队--不带头结点
void EnNoHeadQueue(LinkQueue *Q,ElemType x){

    LinkNode *s =(LinkNode*)malloc(sizeof(LinkNode));
    //申请一个结点s
    s->data=x;
    s->next=NULL;
    if (Q->rear==NULL) {
        Q->front = Q->rear = s;
        printf("元素%d已入队\n",x);
    } else {
        Q->rear->next = s;
        //新结点插入到rear之后
        Q->rear = s;
        printf("元素%d已入队\n",x);
        // 修改表尾指针,
        //入队操作不需要需要表头指针front;
    }
}

其中加入了一个判断:如果队为空(即队尾指向空),加入的是第一个元素,那么头尾都指向他。如果不是第一个元素,那么加入的元素插入到尾指针。
返回标题

链式队列出队

带头结点
//函数功能:带头结点队头元素出队--带头结点
bool DeLinkQueue(LinkQueue *Q,ElemType x){
    if(Q->front->next==NULL){
        printf("空队列,无法出队\n");
        return false;  
         //空队列
    }
    LinkNode *temp =Q->front->next;
    //将头节点的下一个节点储存到temp,用于取出数值
    x=temp->data;    
    //用变量x返回队头元素
    printf("%d已出队\n",x);
    Q->front->next=temp->next;
    //修改队头指针
    if(Q->rear==temp){  
     //考虑最后一个结点出队的情况
        Q->rear=Q->front;
        //修改rear指针
        printf("%d已出队这是队中最后一个元素\n",x);
    }
    free(temp)
     //释放结点空间
    return true;
}

同样的,给该函数输入一个队的位置和一个x变量用于存储出队的元素,调用该函数一次出队一个。
返回标题

不带头结点
//函数功能:不带头结点队头元素出队
void DeNohead_LinkQueue(LinkQueue *Q,ElemType x){
    if(Q->front==NULL){
        return false;    //空队列
    }
    LinkNode *p =Q->front;
    //p指向此次出队的结点
    x=p->data;    
    //用变量x返回队头元素
    Q->front=p->next;
    //↑等价于 Q->front=Q->front->next;
    //修改队头指
    printf("元素%d已出队\n",x);
    if(Q->rear==p){  
    //考虑最后一个结点出队的情况
        Q->rear=NULL;
        Q->front=NULL;
        //修改rear指针
        printf("这是队中最后一个元素\n");
    }
    free(p);  //释放结点空间
    return true;
}

定义一个p指向出队的节点,队头走后p指向下一个元素。同时用队尾是否与p重合来判断是否是最后一个节点出队。
与带头结点不同的是,新建的节点p直接指向出队节点,因为没有头结点。

返回标题

遍历

**链式队列的遍历无论是带不带头结点与普通队列和循环队列的遍历是相同框架的,在此仅做对比展示不做分析。

//函数功能:遍历不带头结点的队列

void traverse_NoHead_LinkQueue(LinkQueue* q) {

    printf("接下来将为您遍历输出队列中的所有元素\n");
    if (q->front == NULL) {
        printf("队列为空.\n");
        return;
    }
    LinkNode* current = q->front;
    while (current!= NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
void traverseLinkQueue(LinkQueue* q) {
    printf("接下来将为您遍历输出队列中的所有元素\n");
    if (q->front->next == NULL) {
        printf("队列为空.\n");
        return;
    }
    LinkNode* current = q->front->next;
    while (current!= NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
void printCircularQueue(SqQueue*q) {
    if (QueueEmpty(*q)) {
        printf("Queue is empty.\n");
        return;
    }
    int index = q->front;
    while (index!= q->rear) {
        printf("%d ", q->data[index]);
        index = (index + 1) % MaxSize;
    }
    printf("\n");
}

返回标题

全部代码展示

返回标题

#include <stdio.h>

#include <stdbool.h>

#include <stdlib.h>

  

//普通队列和循环队列

typedef int ElemType;

#define MaxSize 10

typedef struct SqQueue{

    ElemType data[MaxSize];  

    //用静态数组存放队列元素

    int front,rear;          

    //定义队头指针和队尾指针

}SqQueue;

//链式队列

typedef struct LinkNode{    

//链式队列结点
    ElemType data;
    struct LinkNode *next;
}LinkNode;  

  

typedef struct LinkQueue{              

//链式队列

    LinkNode *front,*rear;  

    //队列的队头和队尾指针

}LinkQueue;

  
  
  

//普通队列和循环队列函数

//函数功能:初始化队列

void InitQueue(struct SqQueue *Q){

    //初始时,队头和队尾指针都指向0;

    Q->rear=Q->front=0;

    printf("已初始化\n");

}

void testQueue(){

    SqQueue Q;    

    printf("已开空间\n");

    //声明一个队列(顺序存储)————这段语句执行后,

    //就会在内存中分配连续大小为MaxSize*sizeof(ElemType)的空间

}

//函数功能:判断队列是否为空

bool QueueEmpty(SqQueue Q){

    if(Q.rear==Q.front) { //队空的条件

        printf("队为空\n");

        return true;}

    else{

        return false;

        printf("队不为空\n");

        }

}

//函数功能:入队

/* bool EnQueue(SqQueue* Q,ElemType x){

    /*if(QueueEmpty(*Q)){

        printf("");

        return false;}//报错

    Q->data[Q->rear]=x;  //将x插入到队尾

    Q->rear=Q->rear+1;  // 队尾指针后移

    printf("%d",x);

    return true;

}*/

  

bool  QueueFull(SqQueue* Q){

    if((Q->rear+1)%MaxSize==Q->front)//判断队空或满

        {   printf("队满\n");

            return false;}//报错

        else

        {printf("队未满\n");

        return true ;}

  

}

//循环队列入队

bool EnQueue(SqQueue* Q,ElemType x){

    //if(队列已满)

    if((Q->rear+1)%MaxSize==Q->front)//判断队空或满

        return false;//报错

    Q->data[Q->rear]=x;  //将x插入到队尾

    Q->rear=(Q->rear+1)%MaxSize;  // 队尾指针加一取模

    //这个语句的操作,使得Q.rear的取值范围固定在了{0,1,2,3,...,MaxSize-1}。

    //可以理解将存储空间变成了“环状”。

    printf("入队元素为%d\n",x);

    return true;

}

//循环队列出队

//函数功能:出队——删除一个队头元素,并用x返回

bool DeQueue(SqQueue *Q,ElemType x){

    if(Q->rear==Q->front)

        return false;//队列为空,报错

    x=Q->data[Q->front];//队头元素赋值给x;

    Q->front=((Q->front+1)%MaxSize);

    printf("出队已完成,出队元素为%d\n",x);

    //队头指针加一取模保证在循环队列中队头指针后移;

    return true;

}

//函数功能:获得队头元素的值,用x返回。

bool GetHead(SqQueue *Q,ElemType x){

    if(Q->rear==Q->front){

        printf("队为空,无法出队");

        return false;

        }

        else {//队空,无元素,报错;

    x=Q->data[Q->front];

    printf("队头为%d\n",x);

    return true;}

}

  

bool searchInCircularQueue(SqQueue*q,int target) {

    int index = q->front;
    while (index!= q->rear) {
        if (q->data[index] == target) {
            return true;
        }
        index = (index + 1) % MaxSize;
    }
        return false;
    }
void  FindElement(SqQueue*q,int target){
    if (searchInCircularQueue(q, target)==true) {
        printf("%d 元素在该队列中.\n", target);
    } else {
        printf("%d 元素不在该队列中.\n", target);
    }
}
//遍历输出
void printCircularQueue(SqQueue*q) {
    if (QueueEmpty(*q)) {
        printf("Queue is empty.\n");
        return;
    }
    int index = q->front;
    while (index!= q->rear) {
        printf("%d ", q->data[index]);
        index = (index + 1) % MaxSize;
    }
    printf("\n");
}
//链式队列

//函数功能:初始化队列--带头结点
void InitLinkQueue (LinkQueue *Q){
    //初始化时,front 和rear指针都指向头结点
    Q->front=Q->rear
    =(LinkNode*)malloc(sizeof(LinkNode));
    Q->front->next=NULL;
    printf("已初始化一个链式队列\n");
}
//判断队列是否为空

bool LinkIsEmpty(LinkQueue *Q){

    if(Q->front==Q->rear)
     //其实,只有为空时,Q.front==Q.rear,其他条件也没必要考虑了。
        {printf("该链式队列为空\n");
            return true;
        }
    else{
        printf("该链式队列不为空\n");
        return false;
        }
}
//函数功能:带头结点队列新元素入队--带头结点

void EnLinkQueue(LinkQueue *Q,ElemType x){

    LinkNode *newNode =(LinkNode*)malloc(sizeof(LinkNode));//申请一个结点newNode
    newNode->data=x;
    newNode->next=NULL;
    Q->rear->next=newNode;
    //新结点插入到rear之后
    Q->rear=newNode;    
    // 修改表尾指针,入队操作不需要需要表头指针front;
    printf("元素%d已入队\n",x);
}
//函数功能:带头结点队列新元素入队--带头结点

void EnQueueNohead(LinkQueue *Q,ElemType x){
    LinkNode *s =(LinkNode*)malloc(sizeof(LinkNode));
    //申请一个结点s
    s->data=x;
    s->next=NULL;
    if (LinkIsEmpty(Q)) {
        Q->front = Q->rear = s;
    } else {
        Q->rear->next = s;
        //新结点插入到rear之后
        Q->rear = s;
        // 修改表尾指针,
        //入队操作不需要需要表头指针front;
    }
}
//函数功能:带头结点队头元素出队--带头结点

bool DeLinkQueue(LinkQueue *Q,ElemType x){
    if(Q->front->next==NULL){
        printf("空队列,无法出队\n");
        return false;  
         //空队列
    }
    LinkNode *temp =Q->front->next;
    //将头节点的下一个节点储存到temp,用于取出数值
    x=temp->data;    
    //用变量x返回队头元素
    printf("%d已出队\n",x);
    Q->front->next=temp->next;
    //修改队头指针
    if(Q->rear==temp){  
     //考虑最后一个结点出队的情况
        Q->rear=Q->front;
        //修改rear指针
        printf("%d已出队这是队中最后一个元素\n",x);
    }
    free(temp);
     //释放结点空间
    return true;
}
//函数功能:遍历输出队列中的所有元素
void traverseLinkQueue(LinkQueue* q) {
    printf("接下来将为您遍历输出队列中的所有元素\n");
    if (q->front->next == NULL) {
        printf("队列为空.\n");
        return;
    }
    LinkNode* current = q->front->next;
    while (current!= NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
//链式队列不带头结点

//------------------------------

void InitLinkNoHeadQueue (LinkQueue *Q){
     //初始化时,frony 和rear指针都指向NULL
    Q->front = Q->rear = NULL;
    printf("一个不带头节点的链式队列已初始化完毕\n");

}
//函数功能:不带头结点队列新元素入队--带头结点
void En_NoHead_Queue(LinkQueue *Q,ElemType x){
    LinkNode *s =(LinkNode*)malloc(sizeof(LinkNode));
    //申请一个结点s
    s->data=x;
    s->next=NULL;
    if (Q->rear==NULL) {
        Q->front = Q->rear = s;
        printf("元素%d已入队\n",x);
    } else {
        Q->rear->next = s;
        //新结点插入到rear之后
        Q->rear = s;
        printf("元素%d已入队\n",x);
        // 修改表尾指针,
        //入队操作不需要需要表头指针front;
    }
}
//函数功能:不带头结点队头元素出队

bool DeNohead_LinkQueue(LinkQueue *Q,ElemType x){
    if(Q->front==NULL){
        return false;    //空队列
    }
    LinkNode *p =Q->front;
    //p指向此次出队的结点
    x=p->data;    
    //用变量x返回队头元素
    Q->front=p->next;
    //↑等价于 Q->front=Q->front->next;
    //修改队头指针
    printf("元素%d已出队\n",x);
    if(Q->rear==p){  
    //考虑最后一个结点出队的情况
        Q->rear=NULL;
        Q->front=NULL;
        //修改rear指针
        printf("这是队中最后一个元素\n");
    }
    free(p);  //释放结点空间
    return true;
}
//函数功能:遍历不带头结点的队列
void traverse_NoHead_LinkQueue(LinkQueue* q) {
    printf("接下来将为您遍历输出队列中的所有元素\n");
    if (q->front == NULL) {
        printf("队列为空.\n");
        return;
    }
    LinkNode* current = q->front;
    while (current!= NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
void main(){
    int x;
    LinkQueue Q;    //声明一个链式队列
    //带头结点
    InitLinkQueue(&Q);
    LinkIsEmpty(&Q);
    EnLinkQueue(&Q,1);
    EnLinkQueue(&Q,2);
    DeLinkQueue(&Q,x);
    EnLinkQueue(&Q,1);
    EnLinkQueue(&Q,2);
    traverseLinkQueue(&Q);
    //不带头结点
     InitLinkNoHeadQueue(&Q);
    En_NoHead_Queue(&Q,2);
    DeNohead_LinkQueue(&Q,x);
    En_NoHead_Queue(&Q,2);
    En_NoHead_Queue(&Q,2);
    traverse_NoHead_LinkQueue(&Q);
    En_NoHead_Queue(&Q,2);
}
//普通队列和循环队列函数调用
    /*SqQueue q;
    InitQueue(&q);
    QueueEmpty(q);
    QueueFull(&q);
    EnQueue( &q,1);
    EnQueue( &q,5);
    DeQueue(&q, x);
    GetHead(&q,x);
    EnQueue( &q,2);
    EnQueue( &q,4);
    EnQueue( &q,1);
    printCircularQueue(&q);
    //earchInCircularQueue(&q,4);
    FindElement(&q,1);*/
//--------

返回标题

标签:结点,队列,C语言,printf,front,数据结构,rear,指针
From: https://blog.csdn.net/ingorenge/article/details/143080762

相关文章

  • 【数据结构与算法】之龟兔赛跑算法
    目录一、龟兔赛跑算法1.1阶段11.2阶段21.3为什么呢?二、判断是否有环2.1问题描述2.2示例2.3 代码实现三、找到环入口3.1问题描述3.2示例3.3代码实现总结本文主要介绍以环形链表相关的算法,主要采用Java语言实现,这类算法又称Floyd'sTortoiseandHare......
  • C语言趣味编程100例源码分享
    C语言趣味编程100例是学习路上必不可缺的示例,话不多说直接看代码1,百钱百鸡问题include<stdio.h>main(){intcock,hen,chicken;for(cock=0;cock<=20;cock++) /外层循环控制公鸡数量取值范围0~20/for(hen=0;hen<=33;hen++) /内层循环控制母鸡数量取值范围0~30/for(chic......
  • C语言经典20例(输入数组元素,求出最大值和最小值,并输出)
    在c语言中,要实现要实现“输入数组元素,并求出最大值和最小值,并输出”主要步骤主要有以下几步:1.必要的头文件。2.定义数组大小。3.从用户那里接受数组元素的输入4.使用循环遍历数组。找出最大值和最小值5.输出最大值和最小值代码如下:#include<stdio.h>intmain(){......
  • C语言经典20例(二进制数转换为十进制数)
     #include<stdio.h>#include<string.h>//函数原型声明intbinaryToDecimal(constchar*binary);intmain(){charbinary[100];//声明一个字符数组,用于存储用户输入的二进制数,假设最大长度为99intdecimal;//用于存储转换后的十进制数//提示......
  • 明解c语言入门篇练习4-2do语句延伸
    明解c语言练习4-2我们可以看到题目:编写一段程序,像右面这样读取两个整数的值,然后计算出他们之间所有整数的和。上次我发了一段这个练习4-2的代码可以看一下#include<stdio.h>intmain(void){  inta,b,max,min;  intsum=0;  printf("请输入两个整数:......
  • 一个基于队列、多线程的文件转换程序
    importcv2importosimportnumpyasnpimportargparseimportthreadingimportqueueimportloggingfrommultiprocessingimportValue#配置日志记录logging.basicConfig(level=logging.INFO,format='%(asctime)s===%(levelname)s===%(m......
  • 数据结构-----------栈和队列后续
    1队列1.1概念与结构概念:只允许在一端进行插入数据操作,在另一端进行删除元素特殊的线性表,队列具有先进先出的性质入队列:进行插入操作的的一端叫做队尾出队列:进行删除操作的一端叫做队头下面我们来看一下队列的实现队列其实跟单链表是差不多的只不过队列只允许在队尾插入数......
  • 【数据结构】队列(环形缓冲区)的实现
    在学习驱动的过程中,接触到了环形缓冲区的概念,发现这个缓冲区和数据结构中的队列具有惊人的相似之处,因此借此来复习相关知识如果应用层来不及读取数据时,我们可以先将数据放入环形缓冲区中用来记录数据,防止数据丢失。当然,缓冲区越大,那么可以缓存的数据就越多。1.队列的定义队......
  • 【数据结构与算法】之链表经典算法大集合
    本文主要内容是几个关于链表的初级经典算法的分享,都采用Java语言实现,话不多说,立马开始!注意:以下代码有关链表的算法实现均基于以下链表节点类://链表节点类publicclassListNode{intval;ListNodenext;ListNode(){}ListNode(intval){this.val=v......
  • 使用OpenSSl库实现AES-GCM-128算法(C语言)
    在C语言中使用OpenSSL库实现AES-GCM-128算法,并生成GMAC(GaloisMessageAuthenticationCode)消息认证码,通过以下步骤完成:初始化加密环境:创建一个EVP_CIPHER_CTX结构体,用于存储加密过程中的所有必要信息。设置加密算法:指定使用AES-GCM模式,以及密钥和IV(初始化向量)。处理附加认证......