数据结构队列(链式存储)实现
因为队列是一种特殊的线性表,所以本文借助链式线性表的创建做进一步的修改
1、链式线性表创建,插入,删除等API编写(chain_linear_list.c)
/*****************************************************
> File Name : test.c
> Author : xboss
> Mail : 2366006417@qq.com
> Created Time: 2020年06月13日 星期六 15时14分59秒
*****************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include "chain_linear_list.h"
/***************************************
function :链式线性表创建
parameter:无
return :链式线性表数据对象的首地址
****************************************/
LinkList* LinkList_Create()
{
TLinkList *tep = (TLinkList *)malloc(sizeof(LinkList));
//malloc后置0
memset(tep,0,sizeof(LinkList));
tep->length = 0;
tep->head.next = NULL;
return tep;
}
/***************************************
function :链式线性表销毁
parameter:链式线性表数据对象的首地址
return :无
****************************************/
void LinkList_Destory(LinkList *list)
{
if(list != NULL)
{
free(list);
list = NULL;
}
return ;
}
/***************************************
function :链式线性表清除(让链表回到初始值)
parameter:链式线性表数据对象的首地址
return :无
****************************************/
void LinkList_Clear(LinkList *list)
{
TLinkList *tlist = NULL;
if(list == NULL)
{
return ;
}
tlist = (TLinkList *)list;
tlist->length = 0;
tlist->head.next = NULL;
return ;
}
/***************************************
function :链式线性表长度计算
parameter:链式线性表数据对象的首地址
return :链式线性表长度
****************************************/
int LinkList_Length(LinkList *list)
{
TLinkList *tlist = NULL;
if(list == NULL)
{
return -1;
}
tlist = (TLinkList *)list;
return tlist->length;
}
/***************************************
function :链式线性表数据插入
parameter:链式线性表数据对象的首地址,插入的链表子节点,插入的位置
return :成功返回0,失败返回-1
****************************************/
int LinkList_Insert(LinkList *list,LinkListNode *node,int pos)
{
int ret = 0,i= 0;
TLinkList *tlist = NULL;
LinkListNode *current = NULL; //辅助指针变量
if(list == NULL || node == NULL || pos < 0 )
{
ret = -1;
printf("LinkList_Insert err:%d\r\n",ret);
return ret;
}
tlist = (TLinkList *)list;
current = &(tlist->head); //辅助指针指着链表头部
for(i = 0;i<pos && current->next != NULL;i++)//让辅助指针跳到插入位置的前一个位置
{
current = current->next;
}
node->next = current->next; //让node节点连接后续链表
current->next = node; //让前面的链表连接新的node节点
tlist->length++; //长度加1
return 0;
}
/***************************************
function :获取链式线性表指定位置上的数据
parameter:链式线性表数据对象的首地址,获取的位置
return :获取到数据位置的地址
****************************************/
LinkList* LinkList_Get(LinkList *list,int pos)
{
int ret = 0,i= 0;
TLinkList *tlist = NULL;
LinkListNode *current = NULL; //辅助指针变量
if(list == NULL || pos < 0 )
{
ret = -1;
printf("LinkList_Insert err:%d\r\n",ret);
return NULL;
}
tlist = (TLinkList *)list;
current = &(tlist->head); //辅助指针指着链表头部
for(i = 0;i<pos && current->next != NULL;i++)//让辅助指针跳到插入位置的前一个位置
{
current = current->next;
}
return current->next;
}
/***************************************
function :链式线性表删除指定位置的数据
parameter:链式线性表数据对象的首地址,指定位置pos
return :需要删除数据位置的地址
****************************************/
LinkList* LinkList_Delete(LinkList *list,int pos)
{
int ret = 0,i= 0;
TLinkList *tlist = NULL;
LinkListNode *current = NULL; //辅助指针变量
LinkListNode *tem = NULL;
if(list == NULL || pos < 0 )
{
ret = -1;
printf("LinkList_Insert err:%d\r\n",ret);
return NULL;
}
tlist = (TLinkList *)list;
current = &(tlist->head); //辅助指针指着链表头部
for(i = 0;i<pos && current->next != NULL;i++)//让辅助指针跳到插入位置的前一个位置
{
current = current->next;
}
tem = current->next; //缓存被删除节点的位置
current->next = tem->next; //连接节点
tlist->length--;
return tem;
}
#if 0
typedef struct teacher_message
{
LinkListNode node; //让老师对象节点去包含小节点,并且老师节点地址和小链表地址相同,没有偏移量
int age;
char name[64];
}Teacher;
int main(void)
{
Teacher t1,t2,t3;
int ret = 0;
int i = 0;
t1.age = 22;
strcpy(t1.name,"黎明");//向name中拷贝字符串,只能通过strcpy函数完成
t2.age = 13;
strcpy(t2.name,"小刚学长");
t3.age = 14;
strcpy(t3.name,"小东");
LinkList* list = NULL;
//创建顺序线性表
list = LinkList_Create();
if(list == NULL)
{
printf("LinkList_Create\r\n");
exit(1);
}
//向顺序线性表插入数据
ret = LinkList_Insert(list,(LinkListNode *)&t1,0);
ret = LinkList_Insert(list,(LinkListNode *)&t2,0);
ret = LinkList_Insert(list,(LinkListNode *)&t3,0);
//遍历顺序线性表中的元素
for(i = 0;i<LinkList_Length(list);i++)
{
Teacher *temp = (Teacher *)LinkList_Get(list,i);
if(temp == NULL)
{
printf("error");
exit(1);
}
printf("temp->age= %d\r\n",temp->age);
printf("temp->name= %s\r\n",temp->name);
}
//删除顺序线性表中的元素
LinkList_Delete(list,0);
Teacher *temp = (Teacher *)LinkList_Get(list,0);
printf("temp->age= %d\r\n",temp->age);
printf("temp->name= %s\r\n",temp->name);
return 0;
}
#endif
2、链式线性表头文件编写(chain_linear_list.h)
#ifndef _CHAIN_LINEAR_LIST_H
#define _CHAIN_LINEAR_LIST_H
//小链表节点,需要上层去包含此节点例如
/*
typedef struct teacher_message
{
LinkListNode node; //让老师对象节点去包含小节点,并且老师节点地址和小链表地址相同,没有偏移量
int age;
char name[64];
}Teacher;
*/
/*
typedef struct _tag_LinkListNode
{
struct _tag_LinkListNode *next;
}LinkListNode; //小链表节点,需要上层应用去包含此节点
typedef struct _tag_LinkList
{
LinkListNode head; //链表头部
int length; //链式线性表的当前的长度(到底有多少个子节点)
}TLinkList;
*/
typedef struct _tag_LinkListNode
{
struct _tag_LinkListNode *next;
}LinkListNode; //小链表节点,需要上层应用去包含此节点
typedef struct _tag_LinkList
{
LinkListNode head; //链表头部
int length; //链式线性表的当前的长度(到底有多少个子节点)
}TLinkList;
typedef void LinkList;
LinkList* LinkList_Create();
void LinkList_Destory(LinkList *list);
void LinkList_Clear(LinkList *list);
int LinkList_Length(LinkList *list);
int LinkList_Insert(LinkList *list,LinkListNode *node,int pos);
LinkList* LinkList_Get(LinkList *list,int pos);
LinkList* LinkList_Delete(LinkList *list,int pos);
#endif
3、队列创建,入队,出队等API函数编写(linkqueue.c)
/*****************************************************
> File Name : test.c
> Author : xboss
> Mail : 2366006417@qq.com
> Created Time: 2020年06月13日 星期六 15时14分59秒
*****************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include "chain_linear_list.h"
#include "linkqueue.h"
//*********队列是一种特殊的线性表
//*********队列是一种特殊的线性表
//*********队列是一种特殊的线性表
typedef void LinkQueue;
//设计队列底层的数据结构类型
typedef struct _tag_LinkQueueNode
{
LinkListNode node;
void *item; //用来接收上层应用的数据
}TLinkQueueNode;
/***************************************
function :队列创建(链式存储)(创建队列相当于创建链式线性表)
parameter:无
return :队列数据对象的首地址
****************************************/
LinkQueue* LinkQueue_Create()
{
return LinkList_Create();
}
/***************************************
function :队列销毁 (销毁队列相当于销毁链式线性表)
parameter:队列数据对象的首地址
return :无
****************************************/
LinkQueue LinkQueue_Destory(LinkQueue *queue)
{
LinkQueue_Clear(queue);
LinkList_Destory(queue);
return ;
}
/***************************************
function :队列清空(回到初始状态)(先释放删除每一个节点,在clear)
parameter:队列数据对象的首地址
return :无
****************************************/
LinkQueue LinkQueue_Clear(LinkQueue *queue)
{
while(LinkQueue_Length(queue) > 0)
{
LinkQueue_Retrieve(queue);
}
LinkList_Clear(queue);
return ;
}
/***************************************
每一个插入一个数据进队列中,会malloc一个
节点(node),然后将节点通过链表的方式插入
function :数据入队列函数(采用尾部插入数据,从头部取出)(向队列添加元素相当于向链式线性表尾部添加数据)
parameter:队列数据对象的首地址,添加的数据(其地址,需要做一次类型转换)
return :成功返回0,失败返回-1
****************************************/
int LinkQueue_Append(LinkQueue *queue,void *item)
{
int ret = 0;
TLinkQueueNode *temp = NULL;
temp = (TLinkQueueNode *)malloc(sizeof(TLinkQueueNode)); //malloc一个node节点(底层库中的数据格式是TLinkQueueNode,需要强制类型转换为LinkListNode,让大节点强制转化为小节点的数据格式做链式存储)
if(temp == NULL)
{
ret = -1;
printf("fun LinkQueue_Append error :%d\r\n",ret);
return ret;
}
memset(temp,0,sizeof(TLinkQueueNode)); //置零
temp->item = item; //赋值,将用户数据地址赋值给底层void *item
ret = LinkList_Insert(queue,(LinkListNode *)temp,LinkList_Length(queue)); //链式线性表数据尾部插入
if(ret != 0)
{
if(temp != NULL) free(temp);
return ret;
}
return 0;
}
/***************************************
function :数据出队列函数(即出队一个数据相当于删除一个数据)
parameter:队列数据对象的首地址,
return :成功返回需要出队列数据的地址,失败返回NULL
****************************************/
LinkQueue* LinkQueue_Retrieve(LinkQueue *queue)
{
TLinkQueueNode *tep = NULL;
void *ret = NULL;
tep = (TLinkQueueNode *)LinkList_Delete(queue,0);
if(tep == NULL)
{
printf("fun LinkQueue_Retrieve error\r\n");
return NULL;
}
ret = tep->item; //删除前将地址缓存
if(tep != NULL)
{
free(tep);
}
return ret;
}
/***************************************
function :查询队列头部数据(相当于获取链式线性表中0号位置的数据)
parameter:队列数据对象的首地址
return :成功返回队列头部数据的地址,失败返回NULL
****************************************/
LinkQueue* LinkQueue_Header(LinkQueue *queue)
{
TLinkQueueNode *tep = NULL;
void *ret = NULL;
tep = (TLinkQueueNode *)LinkList_Get(queue,0);
if(tep == NULL)
{
printf("fun LinkQueue_Header error\r\n");
return NULL;
}
return tep->item;
}
/***************************************
function :队列长度计算
parameter:队列数据对象的首地址
return :返回队列长度,失败返回-1
****************************************/
int LinkQueue_Length(LinkQueue *queue)
{
return LinkList_Length(queue);
}
typedef struct teacher
{
int age;
int high;
}Teacher;
int main(void)
{
Teacher t1,t2,t3,t4;
int ret = 0;
int i = 0;
t1.age = 22;
t1.high = 110;
t2.age = 13;
t2.high = 130;
t3.age = 14;
t3.high = 140;
t4.age = 16;
t4.high = 666;
LinkQueue *listqueue = NULL;
//创建队列
listqueue = LinkQueue_Create();
if(listqueue == NULL)
{
printf("LinkQueue_Create() error\r\n");
exit(1);
}
//向队列中插入数据(尾插法)
ret = LinkQueue_Append(listqueue,(void *)&t1);
ret = LinkQueue_Append(listqueue,(void *)&t2);
ret = LinkQueue_Append(listqueue,(void *)&t3);
ret = LinkQueue_Append(listqueue,(void *)&t4);
//获取队列的长度和数据队列头数据
printf("Length:%d\r\n",LinkQueue_Length(listqueue));
printf("header->age:%d\r\n",((Teacher *)LinkQueue_Header(listqueue))->age);
//数据出队列
while(LinkQueue_Length(listqueue) > 0)
{
Teacher *temp = NULL;
temp = (Teacher *) LinkQueue_Retrieve(listqueue);
printf("temp->age:%d\r\n",temp->age);
printf("temp->high:%d\r\n",temp->high);
}
//销毁队列
LinkQueue_Destory(listqueue);
return 0;
}
4、队列创建,入队,出队等API函数头文件编写(linkqueue.h)
#ifndef _LINKQUEUE_H
#define _LINKQUEUE_H
typedef void LinkQueue;
LinkQueue* LinkQueue_Create();
LinkQueue LinkQueue_Destory(LinkQueue *queue);
LinkQueue LinkQueue_Clear(LinkQueue *queue);
int LinkQueue_Append(LinkQueue *queue,void *item);
LinkQueue* LinkQueue_Retrieve(LinkQueue *queue);
LinkQueue* LinkQueue_Header(LinkQueue *queue);
int LinkQueue_Length(LinkQueue *queue);
#endif