C语言数据结构队列(链式存储)


数据结构队列(链式存储)实现



因为队列是一种特殊的线性表,所以本文借助链式线性表的创建做进一步的修改

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

运行效果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值