Basic operation and implementation of data structure queue (chained queue)

There is a complete implementation code at the end of this article, which is not easy to write. Please attach a link to this article for reprinting.

content

First, the concept of chain queue

Second, the basic operation of the chain queue

(1) Initialization of the chain team

(2), determine whether the chain team is empty

(3), find the length of the chain queue 

(4) Queue operation

(5), find the first element of the chain team

(6), dequeue operation

(7), the main function

(8), running results

(9), complete code


First, the concept of chain queue

         What is a chained queue? When thinking of a chained queue, everyone should think of the basic operation of a singly-linked list in a sequence table. Let's compare: a singly-linked list uses a head pointer or a tail pointer to implement element insertion and deletion, etc., that is, the head insertion method and tail insertion. As for the chained queue, we all know that the queue is a queue that is dequeued at the head of the queue and then entered at the end of the queue, rather than completing the task in one segment, so we need two pointers to point to the front and rear of the queue, respectively. The two of them perform their respective duties. When the dequeue operation is to be performed, the head pointer front has the final say, and when the enqueue operation is to be performed, the tail pointer rear has the final say.

Constraints: we point the head pointer to the previous position of the first element in the queue, there is nothing in it, it is just a mark, marking it points to a queue, through which the queue can be found, just like a singly linked list Head insertion; while the tail pointer points to the last element of the queue.

Second, the basic operation of the chain queue

         After being familiar with the concept of chained queues, we can define the basic operations of chained queues. The operations are not limited to what I said. According to the actual situation, define the required operations.

(1) Initialization of the chain team

(2), determine whether the chain team is empty

(3), find the length of the chain queue

(4) Queue operation

(5), dequeue operation

(6), find the first element of the chain team, (we can also find the tail element of the chain team)

Three, the specific implementation steps of the basic operation

        First declare a queue node structure, which includes the pointer field next and data field data of this node. Then declare a queue structure, including the head pointer front and tail pointer rear of the queue.

#include <stdio.h>
#include <stdlib.h>
typedef int Elemtype;
//声明一个结构体来表示节点
typedef struct Node
{
     Elemtype data;   //节点数据域
     struct Node * next; //节点指针域
}QueueNode;
//声明一个结构体来定义上面这个结构体的两个指针
typedef struct
{
    QueueNode *front,*rear;//分别指向队首和队尾的指针
}LinkQueue;

(1) Initialization of the chain team

The current chain team is an empty team, so the head pointer, tail pointer and node pointer both point to the same place and point to null.

//首先进行初始化
void Init(LinkQueue *s)
{
    QueueNode * p;
    p=(QueueNode*)malloc(sizeof(QueueNode));//为指向节点的指针分配空间
    p->next=NULL;
    s->front=s->rear=p;     
}

(2), determine whether the chain team is empty

         Because the head pointer and tail pointer we defined at the time of initialization point to the same location marked as null, so we judge whether they point to the same place.

//判断队列是否为空,为空返回真1,不为空返回假0
int Empty(LinkQueue s)
{
    //队空的条件是头指针和尾指针指向相同的地方
    if(s.front==s.rear)
    {
        return 1;
    }
    return 0;
}

(3), find the length of the chain queue 

        We declare a temporary node-type pointer variable p, let it point to the first node of the chain, declare a variable to record the length, when the node pointed to by p is not empty, increase the length by one, and at the same time, the pointer p also moves backward one position.

//求队列长度
int GetLength(LinkQueue s)
{
    //声明一个节点类型的指针
    QueueNode *p;
    //让p指向队列的头指针
    p=s.front;
    //声明一个变量用来记录队列当前长度
    int length=0;
    while(p->next)//当指针p所指的节点不为空时执行循环体
    {
        length++;
        p=p->next;
    }
    return length;//返回当前队列的长度
}

(4) Queue operation

          As we said at the beginning of the article, the enqueue operation is determined by the rear pointer of the queue. We declare a pointer variable p of type node, allocate space for it, then assign the element to be enqueued to it, then point the rear pointer to this node, and then move the rear pointer back one bit. This is very similar to the operation of the tail insertion method of the sequential linked list. You can compare it, and the idea is the same.

//入队操作
 void Add(LinkQueue *s,Elemtype x)
 {
     //声明一个节点类型的指针变量用来存储要入队的元素
     QueueNode *p;
     p=(QueueNode*)malloc(sizeof(QueueNode));
     if(!p){
        printf("内存分配失败\n\n");
        return;
     }
     p->data=x;        //指针指向的节点的数据域存放x
     p->next=NULL;     //指针指向的节点的指针域置为空
     s->rear->next=p;   //将队列的尾指针的指针域next指向指针p所指的节点
     s->rear=p;         //将队列的尾指针向后移一位,指向刚入队的节点的位置
 }

(5), find the first element of the chain team

           We only ask for the head element here, not the tail element. When seeking the head element of the queue, we need to determine whether the queue is an empty queue. If it is not empty, we will perform the operation of seeking the first element of the queue. Directly returns the value of the first element pointed to by the head pointer front.

 //获取队首元素
 Elemtype GetTop(LinkQueue s)
 {
     //首先判断队列是否为空
     if(Empty(s))
     {
         printf("队列为空,无法获取队首元素\n\n");
         return 0;
     }
     return s.front->next->data;//不为空的话就返回队首指针指向的第一个元素的数据域
 }

(6), dequeue operation

       The dequeue operation is determined by the team head pointer front. We need to determine if the queue is empty. We declare a pointer variable p of type node, and point it to the position of the first node of the head element of the queue. Then let e record the value of the currently dequeued element. Point the head pointer to the next node of the first node. This is very similar to the delete operation of the head insertion method of the sequential linked list. Remember to free the pointer to the dequeued node.

 //出队操作
 void Del(LinkQueue *s,Elemtype *e)
 {
     //先判断队列是否为空
     if(Empty(*s))
     {
         printf("当前队列为空,无法执行出队操作\n\n");
         return;
     }
     //用临时变量保存出队的元素
     QueueNode *p;
     p=s->front->next;
     if(p==s->rear)    //如果p指向了队尾节点
     {
         s->front=s->rear;  //那么删除之后队首指针和尾指针指向同一个位置
     }
     *e=p->data;
     s->front->next=p->next;//将队首指针指向第一个节点的下一个节点。
     free(p);

 }

(7), the main function

int main()
{
    //声明一个节点类型的变量
    Elemtype e;
    //声明一个顺序队名字为s
    LinkQueue s;
    //对这个顺序队进行初始化
    Init(&s);
    printf("==============================================================\n");
    printf("当前队列是否为空,为空返回真1,不为空返回假0:%d\n\n",Empty(s));
    printf("当前队列的长度为:%d\n\n",GetLength(s));
    //执行入队操作
    Add(&s,5);
    Add(&s,4);
    Add(&s,6);
    Add(&s,2);
    printf("==============================================================\n");
    printf("当前队列是否为空,为空返回真1,不为空返回假0:%d\n\n",Empty(s));
    printf("当前队列的长度为:%d\n\n",GetLength(s));
    //获取当前队首元素
    printf("==============================================================\n");
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }
    //执行出队操作
    printf("==============================================================\n");
    Del(&s,&e);
    printf("出队的元素为:%d,当前队列的长度为:%d\n\n",e,GetLength(s));
    //获取当前队首元素
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }

    //再执行一次出队操作
    printf("==============================================================\n");
    Del(&s,&e);
    printf("出队的元素为:%d,当前队列的长度为:%d\n\n",e,GetLength(s));
    //获取当前队首元素
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }
    //再执行一次出队操作
    printf("==============================================================\n");
    Del(&s,&e);
    printf("出队的元素为:%d,当前队列的长度为:%d\n\n",e,GetLength(s));
    //获取当前队首元素
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }
    return 0;
}

(8), running results

(9), complete code

#include <stdio.h>
#include <stdlib.h>
typedef int Elemtype;
//声明一个结构体来表示节点
typedef struct Node
{
     Elemtype data;   //节点数据域
     struct Node * next; //节点指针域
}QueueNode;
//声明一个结构体来定义上面这个结构体的两个指针
typedef struct
{
    QueueNode *front,*rear;//分别指向队首和队尾的指针
}LinkQueue;
//首先进行初始化
void Init(LinkQueue *s)
{
    QueueNode * p;
    p=(QueueNode*)malloc(sizeof(QueueNode));
    p->next=NULL;
    s->front=s->rear=p;
}
//判断队列是否为空,为空返回真1,不为空返回假0
int Empty(LinkQueue s)
{
    //队空的条件是头指针和尾指针指向相同的地方
    if(s.front==s.rear)
    {
        return 1;
    }
    return 0;
}
//求队列长度
int GetLength(LinkQueue s)
{
    //声明一个节点类型的指针
    QueueNode *p;
    //让p指向队列的头指针
    p=s.front;
    //声明一个变量用来记录队列当前长度
    int length=0;
    while(p->next)//当指针p所指的节点不为空时执行循环体
    {
        length++;
        p=p->next;
    }
    return length;//返回当前队列的长度
}
//入队操作
 void Add(LinkQueue *s,Elemtype x)
 {
     //声明一个节点类型的指针变量用来存储要入队的元素
     QueueNode *p;
     p=(QueueNode*)malloc(sizeof(QueueNode));
     if(!p){
        printf("内存分配失败\n\n");
        return;
     }
     p->data=x;        //指针指向的节点的数据域存放x
     p->next=NULL;     //指针指向的节点的指针域置为空
     s->rear->next=p;   //将队列的尾指针的指针域next指向指针p所指的节点
     s->rear=p;         //将队列的尾指针向后移一位,指向刚入队的节点的位置
 }
 //获取队首元素
 Elemtype GetTop(LinkQueue s)
 {
     //首先判断队列是否为空
     if(Empty(s))
     {
         printf("队列为空,无法获取队首元素\n\n");
         return 0;
     }
     return s.front->next->data;//不为空的话就返回队首指针指向的第一个元素的数据域
 }
 //出队操作
 void Del(LinkQueue *s,Elemtype *e)
 {
     //先判断队列是否为空
     if(Empty(*s))
     {
         printf("当前队列为空,无法执行出队操作\n\n");
         return;
     }
     //用临时变量保存出队的元素
     QueueNode *p;
     p=s->front->next;
     if(p==s->rear)
     {
         s->front=s->rear;
     }
     *e=p->data;
     s->front->next=p->next;
     free(p);

 }
int main()
{
    //声明一个节点类型的变量
    Elemtype e;
    //声明一个顺序队名字为s
    LinkQueue s;
    //对这个顺序队进行初始化
    Init(&s);
    printf("==============================================================\n");
    printf("当前队列是否为空,为空返回真1,不为空返回假0:%d\n\n",Empty(s));
    printf("当前队列的长度为:%d\n\n",GetLength(s));
    //执行入队操作
    Add(&s,5);
    Add(&s,4);
    Add(&s,6);
    Add(&s,2);
    printf("==============================================================\n");
    printf("当前队列是否为空,为空返回真1,不为空返回假0:%d\n\n",Empty(s));
    printf("当前队列的长度为:%d\n\n",GetLength(s));
    //获取当前队首元素
    printf("==============================================================\n");
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }
    //执行出队操作
    printf("==============================================================\n");
    Del(&s,&e);
    printf("出队的元素为:%d,当前队列的长度为:%d\n\n",e,GetLength(s));
    //获取当前队首元素
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }

    //再执行一次出队操作
    printf("==============================================================\n");
    Del(&s,&e);
    printf("出队的元素为:%d,当前队列的长度为:%d\n\n",e,GetLength(s));
    //获取当前队首元素
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }
    //再执行一次出队操作
    printf("==============================================================\n");
    Del(&s,&e);
    printf("出队的元素为:%d,当前队列的长度为:%d\n\n",e,GetLength(s));
    //获取当前队首元素
    e=GetTop(s);
    if(e){
        printf("当前队列的队首元素为:%d\n\n",e);
    }
    return 0;
}

Summary: Learn to compare the sequence table, stack, and team here. There are many similarities, and each has its own uniqueness. Combined with my previous articles on data structure, you can compare it yourself.

Please respect the results of labor, and please indicate the original link and source for reprinting.

Guess you like

Origin blog.csdn.net/BaoITcore/article/details/121315166