【详述】C语言如何构建通用链表,如何使用通用链表

目录

 

前置条件

函数声明

函数实现


 

前置条件:

1.结点的结构体:

typedef struct node{
	void *data;
	struct node *next;
}NODE_T;

       结构体的内容分为数据域和指针域,其中数据域定义为void*的指针,目的是使结点可以接受任意类型的数据。这个数据只需要在堆区开辟一个空间来存放,然后把堆区的地址传送给data即可。(具体见下文代码)

2.该链表是带头结点的单向链表,头结点不放数据

      带头结点方便进行数据的操作,计算结点个数时不包括头结点,链表的第一个位置指带有数据的第一个结点。但在释放整条链表时也要释放头结点。

函数声明:


/*
函数名:List_init
函数功能:创建链表头结点
函数参数:	无
函数返回值:头结点地址
*/
NODE_T *List_init();


/*
函数名:List_add
函数功能:添加链表结点
函数参数:	head--链表头结点
			data--添加的数据
函数返回值:无
*/
void List_add(NODE_T *head,void *data);

/*
函数名:getListCount
函数功能:计算结点个数
函数参数:	head--链表头结点
函数返回值:结点个数
*/
int getListCount(NODE_T *head);

/*
函数名:findListByPos
函数功能:根据位置查找结点
函数参数:	head--链表头结点
			pos--位置
函数返回值:查找到的结点
*/
void *findListByPos(NODE_T *head,int pos);


/*
函数名:InsertListByPos
函数功能:在某个位置插入结点
函数参数:	head--链表头结点
			pos--位置
			data--插入的数据
函数返回值:1--成功,0--失败
*/
int insertListByPos(NODE_T *head,int pos,void *data);

/*
函数名:DeleteListBYPos
函数功能:删除某个位置的结点
函数参数:	head--链表头结点
			pos--位置
函数返回值:1--成功,0--失败
*/
int deleteListByPos(NODE_T *head,int pos);

/*
函数名:freeList
函数功能:删除整条链表(包括头结点)
函数参数:	head--链表头结点
函数返回值:头结点
*/
void *freeList(NODE_T *head);

函数实现:


NODE_T *list_init()
{
	NODE_T *head = NULL;
	head = (NODE_T*)malloc(sizeof(NODE_T));
	if(!head)
	{
		printf("开空间失败!\n");
		exit(0);
	}
	memset(head,0x0,sizeof(NODE_T));//初始化结点
	head->next = NULL;
	return head;
}


void list_add(NODE_T *head,void *data)
{
	//新建一个结点
	NODE_T *newnode = NULL;
	newnode = (NODE_T*)malloc(sizeof(NODE_T));
	if(!newnode)
	{
		printf("开空间失败!\n");
		exit(0);
	}
	memset(newnode,0x0,sizeof(NODE_T));
	newnode->next = NULL;
	//赋值
	newnode->data = data;
	//找到尾结点
	while(head->next)
	{
		head = head->next;
	}
	//添加结点
	head->next = newnode;
}

int getListCount(NODE_T *head)
{
	int count = 0;
	while(head->next)
	{
		count ++;
		head = head->next;
	}
	return count;
}

void *findListByPos(NODE_T *head,int pos)
{
	if(pos > getListCount(head))
	{
		printf("位置大于总结点数。\n");
		return NULL;
	}
	while(pos>0)
	{
		head = head->next;
		pos--;
		
	}

	return head->data;

}

int insertListByPos(NODE_T *head,int pos,void *data)
{
	//找到插入位置(准确说是找到pos位置的结点的前一个)
	NODE_T *newnode =NULL;
    NODE_T *q = head->next;
	if(pos < 1)
	{
		printf("插入的位置要>=1\n");
		return 0;
	}
	if(pos > getListCount(head))
	{
		printf("插入的位置大于总结点数。\n");
		return 0;
	}
	while(pos>1)
	{
		head = q;
		q = head->next;
		pos--;
	}
	//新建一个结点
	newnode = (NODE_T*)malloc(sizeof(NODE_T));
	if(!newnode)
	{
		printf("开空间失败!\n");
		exit(0);
	}
	memset(newnode,0x0,sizeof(NODE_T));
	newnode->next = NULL;
	newnode->data = data;
	//插入
	head->next = newnode;
	newnode->next = q;
	
	return 1;
}

int deleteListByPos(NODE_T *head,int pos)
{
	//找到这个位置(其实也是找到前一个位置)
	NODE_T *q = head->next;
	if(pos < 1)
	{
		printf("删除位置要>=1\n");
		return 0;
	}
	if(pos > getListCount(head))
	{
		printf("删除位置大于总结点数。\n");
		return 0;
	}
	while(pos>1)
	{
		head = q;
		q = head->next;
		pos--;
	}
	//删除
	head->next = q->next;
	free(q->data);
	free(q);

	return 1;
}

void *freeList(NODE_T *head)(比较简单的写法)
{
	NODE_T *p = NULL;
	//每次找到最后一个位置,释放
	while(head->next)//循环条件即还存在数据结点
	{
		p = head;
        //调用删除单个结点和统计结点个数的函数,每次都删除最后一个结点。
		deleteListByPos(p,getListCount(p));
	}
	//释放头结点
	free(head->data);
	free(head);
	head = NULL;

	return NULL;
}

注意,释放结点的时候要先释放结点的数据,再释放整个结点。

C语言链表:函数内部对头结点head的修改为什么不会改变外面的head?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿峰不想搬砖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值