首页 > 其他分享 >数据结构C语言|队列相关

数据结构C语言|队列相关

时间:2024-10-19 20:48:49浏览次数:1  
标签:结点 队列 C语言 printf front 数据结构 rear 指针

队列

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

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

结构体

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-> 我是空间s NULL
[ 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://www.cnblogs.com/HANEhane820/p/18486553

相关文章

  • C语言解决约瑟夫环(PTA链表)
    题意:就是N个人围成一个圈(想到循环),开始报数,报到一个指定的数p,则这个人出局,后延,比如本题的样例,第三个人报了3,则第四个人继续从1开始报数,一直循环下去,第七个人报完之后,再到第一个人,直到只剩下一个人,那么下一个出局的只剩下这个人。解题思路:我们看到,最后一个人报数之后,又回到了......
  • C语言 【操作符(上)】
        最开始提到C语言操作符,我还是有一些不屑的,这玩意有啥学的呀?今天静下心来阅读学习了一下操作符部分的知识,这部分还真得认真学习学习!下面我将操作符中一些比较关键的点进行罗列和详细说明。一来帮助我加深理解,二来希望能帮助到有缘点击进来的读者。1、算术操作符:+ ......
  • [数据结构]进制转换
    要求实现函数,借助如下自定义栈seqstack将一个正整数n转换为$$进制数并输出。输出时用大写字母A、B、C、D、E、F分别表示10、11、12、13、14、15。#include<iostream>#defineMAXSIZE100usingnamespacestd;typedefstruct{intdata[MAXSIZE];inttop;}seqs......
  • leetcode:栈和队列oj题
    目录1.有效的括号2.用队列实现栈                                        3.用栈实现队列                              ......
  • 考研数据结构-串(串的模式匹配算法)
             串的基本操作可以参照考研数据结构-串(串的基本操作),除去这些基本操作外,还有一个重要的操作就是串的模式匹配算法。模式匹配算法就是,对于一个串中某个子串的定位操作,这里会讲两种模式匹配算法:简单模式匹配算法和KMP算法。一、简单模式匹配算法   简单......
  • C语言经典游戏代码大全(珍藏版)
    前言发现很多朋友都想要一些小项目来练手,却找不到从哪里寻找,给大家整理了游戏项目开发源代码汇总。一、最经典游戏之俄罗斯方块#include<iostream>#include<math.h>#include<Windows.h>#include<conio.h>#include<ctime>usingnamespacestd; enumDIR{   UP......
  • 【数据结构与算法】之二分查找
    二分查找(BinarySearch)是一种在有序数组中查找特定元素的搜索算法。它通过比较数组中间元素与目标值来工作,从而将搜索范围缩小到一半,也称折半查找,是一种非常高效的工作于有序数组的查找算法。本文主要介绍二分查找及其几个变种,包括基础版、改变版、平衡版和Java版,以及Leftmost......
  • 「图::连通」详解并查集并实现对应的功能 / 手撕数据结构(C++)
    目录概述成员变量创建销毁根节点访问路径压缩启发式合并复杂度Code概述并查集,故名思议,能合并、能查询的集合,在图的连通性问题和许多算法优化上着广泛的使用。这是一个什么数据结构呢?一般来讲,并查集是由一系列集合组成的集合群。其中,每个集合都有一个根节点,它的......
  • Linux C语言TCP协议实战
    文章目录1.TCP简介2.搭建框图3.相关函数介绍3.1socket函数3.2bind函数3.3listen函数3.4accept函数3.5connect函数3.6send函数3.7recv函数3.8其他函数4.实战4.1一对一模型4.1.1server.c4.1.2client.c4.1.3终端结果4.2多进程模型4.2.1server.c4.2.2cl......
  • 汉诺塔问题和青蛙跳台阶问题(c语言)
     这俩道题都是利用到了函数递归的思想,其中汉诺塔问题较难理解,青蛙跳台阶则较简单汉诺塔问题题述:设有三根柱子分别时A,B,C,在A柱子上放着n个盘子,每个盘子大小不一样,从下往上盘子大小依次减小,要求将A柱子上的盘子移动到C柱,且不改变盘子顺序(由大往小排序)。规则:1.一次只能......