c语言实现的万能链表

c语言实现的万能链表

起因

   c++里面有模板,可以很容易实现链表,栈等数据结构。可我用的是C语言,每次用到链表,都要重新写一次那几个函数,很麻烦,今天突然想到了之前看的一本书,于是想到了解决办法,其实别人早就做了,只是我啥也不会,到现在才明白。如下,链表节点存储一个指针,指向存储元素的副本。


typedef struct LIST
{
	void *pval;			//指向元素的指针,以此可以存储任意类型 
	struct LIST  *next;	//不说了,你也懂 
}LIST;

接下来,就是实现了

  写在前面,我发现如果要想在函数实参列表得到返回值,那么就需要传递这个形参的指针,这个是我在下面查找元素的函数实现过程中醒悟的,虽然晚了点。

初始化

LIST* LIST_Init(void)
{
	LIST *head;
	head = (LIST*)malloc(sizeof(LIST));
	head->next = NULL;		//初始化的值必须是 NULL 
	head->pval = NULL;
	return head;
}

添加元素

//正确执行,返回0,否则返回错误代码,
//@param ArrElement:需要添加的元素数组的地址
//@param ElemenNum:需要添加的元素数组的长度 
//@param ElementSize:需要添加的元素的大小,以字节为单位 
int LIST_add(LIST *head,void *ArrElement,int NumOfArrElement,int ElementSize)
{
	if(head==NULL)
		return ptr_null;	//ERROR_CODE类型,强制转换为整形输出了
	int i=0;
	LIST *temp,*pre=head;
	void *ptr_val=NULL;
	while(pre->next)		//遍历到 LIST 的尾节点 
	{
		pre = pre->next;
	}
	for(i=0;i<NumOfArrElement;i++)
	{
		temp = (LIST*)malloc(sizeof(LIST));	//分配LIST节点的内存 
		if(temp==NULL)		//如果没有申请到内存,直接返回错误代码,结束函数 
			return mem_NotEnough;
		temp->next = NULL;
		temp->pval = NULL;	//初始化的值必须是 NULL 
		
		pre->next = temp;	
		pre = temp;			//将指针后移到新分配的节点 
		
		ptr_val = malloc(ElementSize);		//分配存储元素的内存 
		if(ptr_val==NULL)
			return mem_NotEnough;
		memcpy(ptr_val,ArrElement+i*ElementSize,ElementSize);	//将元素存储到分配的内存中 
		temp->pval = ptr_val;		
	}
	return 0; 
} 

查找元素
//@param List ptr_ret:返回的链表节点的指针,注意是二级指针,

//如果找到,返回0,没有返回出错代码
//@param void *Element :要寻找的元素的地址,考虑到以后会寻找结构体,使用地址会很方便
//@param int ElemenSize:元素的大小,sizeof(ElementType),以字节计算
//@param List **ptr_ret:返回的链表节点的指针, 注意是二级指针, 
int  LIST_GetElement(LIST *head,void *Element,int ElementSize,LIST **ptr_ret)
{
	if(head==NULL)
		return ptr_null;	//ERROR_CODE类型,强制转换为整形输出了
	
	LIST *temp=head->next;
	while(temp)
	{
		if(memcmp(temp->pval,Element,ElementSize))	//如果不相等,下一个 
		{
			temp = temp->next;
		}
		else
		{
			*ptr_ret = temp;
			return 0;				//如果找到了,直接返回, 
		}	
	}	
}

删除某个元素

int  LIST_deleteElement(LIST *head,void *Element,int ElementSize)
{
	if(head==NULL)
		return ptr_null;	//ERROR_CODE类型,强制转换为整形输出了
	
	LIST *temp=head,*aim=NULL;
	while(temp)
	{
		if(memcmp(temp->next->pval,Element,ElementSize))	//如果不相等,下一个 
		{
			temp = temp->next;
		}
		else
		{
			break;				//如果找到了,直接返回, 
		}	
	}
	if(memcmp(temp->next->pval,Element,ElementSize))	//如果是循环结束
	{
		return No_Element;
	 } 
	 else 	//找到了元素 
	 {
	 	aim = temp->next;
	 	temp->next = aim->next;
	 	free(aim->pval);
	 	free(aim);
	 	return 0;
	 }	
}

删除这个链表

void List_destroy(LIST* head)
{
	if(head==NULL)
		return ;
	LIST *temp=head->next,*temp_next=temp->next;		//头节点最后释放 
	void *pval;
	while(temp_next)
	{
		free(temp->pval);
		free(temp);
		temp = temp_next;
		temp_next = temp_next->next;
	}
	free(temp->pval);		//释放最后一个节点 
	free(temp);
	
	free(head);		//释放头节点	
}

测试代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"list.cpp"
#include"Sort.cpp"

#define ArrSize  9 
#define POSTION  8
#define DELE_POS 1 

int main(int argc,char **argv)
{
	LIST *head;
	LIST *temp;

	int arr[ArrSize]={1,2,3};
	InitArr(arr,ArrSize,ArrSize*30);	//我自己另外实现的 
	PrintArr(arr,ArrSize);				//我自己另外实现的 
	
	head = LIST_Init();
	if(!LIST_add(head,arr,ArrSize,sizeof(int)))
	{
		temp=head->next;
		while(temp->next)
		{
			printf("val is %d\n",*(int*)temp->pval);
			temp=temp->next; 
		}
		printf("val is %d\n",*(int*)temp->pval);
		
	}
	if(!LIST_GetElement(head,&arr[POSTION],sizeof(int),&temp))
		printf("need get val is %d,get value is %d\n",arr[POSTION],*(int*)temp->pval);
	
	LIST_deleteElement(head,&arr[DELE_POS],sizeof(int));
	temp=head->next;
	while(temp->next)
	{
		printf("val is %d\n",*(int*)temp->pval);
		temp=temp->next; 
	}
	printf("val is %d\n",*(int*)temp->pval);	//打印最后一个元素 
	
	printf("链表删除以后\n");
	List_destroy(head);
	
	head=NULL;	// free以后,head 一定要指向 null 
	 
	return 0;
}

结果
测试输出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值