前几天做了海康威视的笔试题,正好大题遇上了用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这是一种简单的处理方法,还有一种可以给自己加分的方法:就是用循环队列的思想去解决;