C语言回顾--队列的入队和出队

-------------------------------------------------------------------------------------------

前言:

前几天做了海康威视的笔试题,正好大题遇上了用C语言编程实现队列的入队和出队功能;于是考完后就自己调试当时所写的代码,错误颇多,经过几小时的努力调试成功,特定发到博客上分享给大家。

-------------------------------------------------------------------------------------------

队列:就跟排队买饭一样,先到者先买饭,买完就离开,后来的人只能排队,也就是先进先出;因此,本次编程我以链表的形式来实现题目需求;

那这么表示一个队列的头和尾呢?这里,我们引入2指针,分别是指向第一个节点的头指针,指向尾节点的尾指针,那如何移动呢?你可以想一下,买饭的时候是一个接一个的排队,但是买饭的窗口是固定的,你只有到窗口,阿姨才问你吃什么饭,然后打菜给你,拿到了饭你也就走了,轮到下一个人买,也就是说指针pTailNode一直向后移,而pHeadNode一直在处理这些人所需要处理的事情,所以说先进先出的这个道理。再简单一句话,你pTailNode一直在给pHeadNode找麻烦,而pHeadNode又像爸爸一样给你搽屁股的解决这些事;

下面是代码流程:

结构体定义如下:

typedef struct _QUEUE_NODE_         //一个节点的结构体   
{
    struct _QUEUE_NODE_ *pNextNode;
    int                       data;
}QUEUE_NODE,*PQUEUE_NODE;

说明:
1.海康威视里面存放的数据是void *类型,本实验就用简单的int 类型来代替;
2.定义一个结构体类型名为_QUEUE_NODE_,并且用该结构体类型名命名一个叫QUEUE_NODE,它等价于QUEUE_NODE = struct _QUEUE_NODE_ ,而*PQUEUE_NODE呢?
同样,*PQUEUE_NODE = (struct _QUEUE_NODE_ *),所以调用时只需QUEUE_NODE,PQUEUE_NODE即可;
3.该结构体中含有1个数据类型,1个结构体指针类型(用于连接下一个节点);
typedef struct QUEUE        //链表的结构体
{
    QUEUE_NODE *pHeadNode;
    QUEUE_NODE *pTailNode;
}QUEUE_HANDLE,*PQUEUE_HANDLE;

说明:
1.海康威视省略了定义结构体名为QUEUE,这里是我添加的,有无并不影响调用QUEUE_HANDLE和PQUEUE_HANDLE;
2.与第一个结构体相同,QUEUE_HANDLE = struct QUEUE ;PQUEUE_HANDLE = (struct QUEUE *);
3.该结构体内有2个指针,一个是头指针,pHeadNode用于标识这个链表的第一个节点,pTailNode用于标识这个链表的最后一个节点;

入队的函数: 

QUEUE_HANDLE *insert(QUEUE_HANDLE *HQ,int Data)    //入队
{
    PQUEUE_NODE s;

    if(HQ == NULL)                                   //传参检查
    {
        printf("HQ value is NULL.\n"); 
        return NULL;
    }

    s = (QUEUE_NODE *)malloc(sizeof(QUEUE_NODE));    //新节点分配
   
    s->data = Data;
    s->pNextNode = NULL;

    if(HQ->pTailNode == NULL && HQ->pHeadNode == NULL)    //临界条件:插入第一个节点时
    {
        HQ->pHeadNode = s;
        HQ->pTailNode = s;
    }
    else                            //正常情况
    {
        HQ->pTailNode->pNextNode = s;
        HQ->pTailNode = s;
    }

    return HQ;

}

出队函数:

QUEUE_HANDLE *out(QUEUE_HANDLE *HQ)
{
    QUEUE_NODE *p;
    p = HQ->pHeadNode;
    
    if(p == NULL)
    {
        printf("yichu\n");
        return NULL;
    }
    else
    {
        printf("queue data:%d\n",p->data);
        printf("queue adress:%p\n",p);
        
        if(HQ->pHeadNode == HQ->pTailNode)    //临界条件:只剩最后一节点时
        {
            HQ->pHeadNode = NULL;
            HQ->pTailNode = NULL;
            free(p);
            p = NULL;                        //防止p访问被Free的内存;

        }
        else        //正常情况
        {
            HQ->pHeadNode = HQ->pHeadNode->pNextNode;
            free(p);
        }

    return HQ;
    }
}

完整的代码:包括遍历函数和使用上述函数的调用;

/*********************************************************************************
 *      Copyright:  (C) 2018 guozhihao
 *                  All rights reserved.
 *
 *       Filename:  homework.c
 *    Description:  This file 
 *                 
 *        Version:  1.1.0(10/27/2019)
 *         Author:  Guozhihao <[email protected]>
 *      ChangeLog:  2, Release initial version on "10/27/2019 08:35:03 PM"
 *                 
 ********************************************************************************/
#include 
#include 
typedef struct _QUEUE_NODE_
{
    struct _QUEUE_NODE_ *pNextNode;
    int                       data;
}QUEUE_NODE,*PQUEUE_NODE;

typedef struct QUEUE
{
    QUEUE_NODE *pHeadNode;
    QUEUE_NODE *pTailNode;
}QUEUE_HANDLE,*PQUEUE_HANDLE;

QUEUE_HANDLE *insert(QUEUE_HANDLE *HQ,int Data)
{
    
    if(HQ == NULL)
    {
        printf("HQ value is NULL.\n"); 
        return NULL;
    }

    PQUEUE_NODE s;
    s = (QUEUE_NODE *)malloc(sizeof(QUEUE_NODE));
   
    s->data = Data;
    s->pNextNode = NULL;

    if(HQ->pTailNode == NULL && HQ->pHeadNode == NULL)
    {
        HQ->pHeadNode = s; 
        HQ->pTailNode = s; 
    }
    else
    {
        HQ->pTailNode->pNextNode = s;
        HQ->pTailNode = s;
    }

    return HQ;

}

QUEUE_HANDLE *out(QUEUE_HANDLE *HQ)
{
    QUEUE_NODE *p;
    p = HQ->pHeadNode;
    
    if(p == NULL)
    {
        printf("yichu\n");
        return NULL;
    }
    else
    {
        printf("queue data:%d\n",p->data);
        printf("queue adress:%p\n",p);
        
        if(HQ->pHeadNode == HQ->pTailNode)
        {
            HQ->pHeadNode = NULL;
            HQ->pTailNode = NULL;
            free(p);
            p = NULL;

        }
        else
        {
            HQ->pHeadNode = HQ->pHeadNode->pNextNode;
            free(p);
            p = NULL;
        }

        return HQ;
    }
}

void travel(QUEUE_HANDLE *HQ)
{
    QUEUE_NODE *p;
   
    p = HQ->pHeadNode;

    while(p != NULL)
    {
        printf("queue data:%d\n",p->data);
        printf("queue adress:%p\n",p);
        
        p = p->pNextNode;
                
    }
}

int main (int argc, char **argv)
{
    QUEUE_HANDLE *HQ ;
    int             i;
    HQ = (QUEUE_HANDLE *)malloc(sizeof(QUEUE_HANDLE));
    
    HQ->pTailNode = NULL;
    HQ->pHeadNode = NULL;
    
    printf("now start to add new node:\n");

    for(i = 0;i<10;i++)
    {
        HQ = insert(HQ,i);
        if(!HQ)
        {
            printf("HQ insert failed.\n"); 
            goto END_EXIT;
        }

    }

    travel(HQ);
    
    printf("now start to free node:\n");

#if 1 
    for(i = 0;i<5;i++)
    {
        HQ = out(HQ);
        if(!HQ)
        {
            printf("HQ is NULL.\n"); 
            goto END_EXIT;
        }
    }
    printf("The remaining node:\n");

#endif
    travel(HQ);

END_EXIT:

   if(HQ) 
   {
       free(HQ);
   }

    return 0;
} /* ----- End of main() ----- */

附上makefile文件:(把makefile放置于zhan.c同级目录下后,在命令行里敲make即可编译)

# /bin/bash

PWD := $(shell pwd)

filename := duilie

testfile :=${PWD}/${filename}

tools:=gcc

all: GCC

GCC:
        ${tools} ${testfile}.c -o ${filename} -Wall
        @echo " gcc ${testfile} successfully!";
        ./${filename}

debug:
        gcc -g ${testfile}.c -o ${filename}
        gdb ${testfile}

cleanup:
        @rm ${filename}

程序运行结果:

[guozhihao@bogon shujujiegou]$ make
gcc /home/guozhihao/Master/guozhihao/C6/shujujiegou/duilie.c -o duilie -Wall
 gcc /home/guozhihao/Master/guozhihao/C6/shujujiegou/duilie successfully!
./duilie
now start to add new node:
queue data:0
queue adress:0x14bd030
queue data:1
queue adress:0x14bd050
queue data:2
queue adress:0x14bd070
queue data:3
queue adress:0x14bd090
queue data:4
queue adress:0x14bd0b0
queue data:5
queue adress:0x14bd0d0
queue data:6
queue adress:0x14bd0f0
queue data:7
queue adress:0x14bd110
queue data:8
queue adress:0x14bd130
queue data:9
queue adress:0x14bd150
now start to free node:
queue data:0
queue adress:0x14bd030
queue data:1
queue adress:0x14bd050
queue data:2
queue adress:0x14bd070
queue data:3
queue adress:0x14bd090
queue data:4
queue adress:0x14bd0b0
The remaining node:
queue data:5
queue adress:0x14bd0d0
queue data:6
queue adress:0x14bd0f0
queue data:7
queue adress:0x14bd110
queue data:8
queue adress:0x14bd130
queue data:9
queue adress:0x14bd150

 

思考:

当pHeadNode指针处理完pTailNode安排的事情之后相遇;双方都将其指向NULL这是一种简单的处理方法,还有一种可以给自己加分的方法:就是用循环队列的思想去解决;

你可能感兴趣的:(学习以及回顾数据结构)