C语言实现带头结点的单链表(可以储存任意数据类型)

C语言实现带头结点的单链表,可以储存任意数据类型,用户可以自定义储存的数据类型,但数据储存的堆空间需要用户自己创建。其中回调函数可以根据用户自己的要求去查找数据结点。

 

list.h

#ifndef _LIST_H_
#define _LIST_H_

typedef int (*keyCmp)(void* pData, char* key);//返回 0 相等  其它 不相等

typedef struct list_s
{
	void* pData;
	struct list_s* next;
}List, * pList;

int createList(pList* pHead);//创建链表
int add(pList* pHead, void* pData);//添加结点(尾插)
void outList(pList pHead);//遍历链表
void* findNode(pList pHead, keyCmp cmpFun, char* key);//查找指定结点
int delNote(pList pHead, keyCmp cmpFun, char* key);//删除结点
void freeList(pList* pHead);//删除链表

#endif

 

list.c

#include <stdio.h>
#include "list.h"

int createList(pList* pHead)//创建链表
{
	pList p = (pList)malloc(sizeof(List));
	if (p == NULL)
	{
		return -1;
	}
	p->next = NULL;
	*pHead = p;

	return 0;
}

int add(pList * pHead, void* pData)//添加结点(尾插)
{
	pList* p = pHead;
	pList pNew = (pList)malloc(sizeof(List));
	if (pNew == NULL)
	{
		return -1;
	}
	pNew->pData = pData;
	pNew->next = NULL;
	while (*p != NULL)
	{
		p = &((*p)->next);
	}
	*p = pNew;

	return 0;
}

void outList(pList pHead)//遍历链表
{
	printf("链表数据:\n");
	while (pHead != NULL)
	{
		pHead = pHead-> next;
		if (pHead != NULL)
		{
			printf("%s\n",(char *)pHead->pData);
		}
	}
}

void* findNode(pList pHead, keyCmp cmpFun, char* key)//查找指定结点
{
	pList p = pHead->next;
	while (p != NULL)
	{
		if (cmpFun(p->pData, key) == 0)
		{
			break;
		}
		p = p->next;
	}

	return p;
}

int delNote(pList pHead, keyCmp cmpFun, char* key)//删除结点
{
	pList p = pHead->next;
	pList q = pHead;
	while (p != NULL)
	{
		if (cmpFun(p->pData, key) == 0)
		{
			q->next = p->next;
			free(p->pData);//删除用户堆空间数据
			free(p);//删除结点空间

			return 0;
		}
		q = p;
		p = p->next;
	}

	return -1;
}

void freeList(pList* pHead)//删除链表
{
	pList p = (*pHead)->next;//跳过头结点
	pList pTemp = NULL;

	while (p != NULL)
	{
		pTemp = p->next;
		free(p->pData);//删除用户堆空间数据
		free(p);//删除结点空间
		p = pTemp;
	}
	//删除头结点
	free(*pHead);//删除头结点空间(头结点没存储用户数据)
	*pHead = NULL;
}

main.c  测试文件

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

int keyFun(void* pData, char* key)
{
	if (strcmp((char*)pData, (char*)key) == 0)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}

int main()
{
	pList root, p;
	char* ch;
	int ret;

	createList(&root);
	ch = (char*)malloc(sizeof(char) * 2);
	strcpy(ch, "a");
	add(&root, ch);
	ch = (char*)malloc(sizeof(char) * 2);
	strcpy(ch, "b");
	add(&root, ch);
	ch = (char*)malloc(sizeof(char) * 2);
	strcpy(ch, "c");
	add(&root, ch);
	outList(root);

	p = findNode(root, keyFun, "b");//查找指定结点
	if (p != NULL)
	{
		printf("查找到的数据: %s\n", (char*)p->pData);
	}
	ret = delNote(root, keyFun, "c");
	if (!ret)
	{
		printf("删除 c 成功!\n");
	}
	outList(root);
	freeList(&root);//删除链表
	outList(root);

	return 0;
}

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是用C语言实现头结点单链表就地逆置的成员函数的代码: ```c #include <stdio.h> #include <stdlib.h> // 定义单链表的结点结构体 typedef struct ListNode { int data; struct ListNode* next; } ListNode; // 初始化头结点单链表 ListNode* initList() { ListNode* head = (ListNode*)malloc(sizeof(ListNode)); head->next = NULL; return head; } // 尾插法建立单链表 void createList(ListNode* head) { int data; ListNode* tail = head; printf("请输入链表中的元素(以-1结束):"); while (1) { scanf("%d", &data); if (data == -1) { break; } ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->data = data; newNode->next = NULL; tail->next = newNode; tail = newNode; } } // 打印头结点单链表 void printList(ListNode* head) { ListNode* p = head->next; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } // 就地逆置头结点单链表 void reverseList(ListNode* head) { ListNode* p = head->next; ListNode* q = p->next; p->next = NULL; // 将第一个结点的指针域赋值为NULL while (q != NULL) { ListNode* r = q->next; q->next = p; p = q; q = r; } head->next = p; // 将头结点的指针域指向原链表的最后一个结点 } int main() { ListNode* head = initList(); createList(head); printf("原链表:"); printList(head); reverseList(head); printf("逆置后的链表:"); printList(head); return 0; } ``` 运行结果: ``` 请输入链表中的元素(以-1结束):1 2 3 4 5 -1 原链表:1 2 3 4 5 逆置后的链表:5 4 3 2 1 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值