两种通用链表(Linux 内核链表)

Linux 内核链表(通用版)

以下是头文件

#define _CRT_SECURE_NO_WARNINGS
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct _Tag_LinkNode  //用来保存下一个节点
{
	struct _Tag_LinkNode *next;
}LinkNode;

typedef void* LLink;

typedef void(*TYPE_PRINT)(LinkNode *);//回调函数,打印

typedef bool(*TYPE_COMPARE)(LinkNode *, LinkNode *);//回调函数,比较

LLink Init_LinkList();//初始化 返回void *类型的指针

void Insert_LinkNode(LLink *head,int pos,LinkNode *data); //插入(通过位置),传递的也是void *类型指针 ,在函数实现内部转换成需要的类型

void PushFront_LinkNode(LLink *head, LinkNode *data);//插入头部

void PushBack_LinkNode(LLink *head, LinkNode *data);//插入尾部

LinkNode * RemoveByPos_LinkNode(LLink *head, int pos);//删除(通过位置)

LinkNode * PopFront(LLink *head);//删除头部

LinkNode * PopBack(LLink *head);//删除尾部

void RemoveByVal_LinkNode(LLink *head, LinkNode * data , TYPE_COMPARE compare);//删除(通过值得比较)

int GetLinkListLen(LLink *head);//获取长度

void Destroy_LinkList(LLink *head);//销毁

void Foreach(LLink *head, TYPE_PRINT print);//遍历打印

#endif

以下是函数的实现:

#include "LinkList.h"

typedef struct _Tag_LinkList //此处对用户隐藏
{
	LinkNode header;
	int size;
}LinkList;

LLink Init_LinkList()//初始化
{
	LinkList *list = (LinkList *)malloc(sizeof(LinkList));
	if (list == NULL)
	{
		return NULL;
	}
	list->header.next = NULL;
	list->size = 0;
	return list;
}
void Insert_LinkNode(LLink *head, int pos, LinkNode *data)
{
	if (head == NULL || data == NULL)
	{
		return;
	}
	LinkList *temp =(LinkList *)head;

	if (pos < 0 || pos > temp->size)//越界转换成尾插
	{
		pos = temp->size;
	}

	LinkNode * pCurrent = &(temp->header);
	
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}

	data->next = pCurrent->next;
	pCurrent->next = data;
	temp->size++;

}
void PushFront_LinkNode(LLink *head, LinkNode *data)//头插
{
	if (head == NULL || data == NULL)
	{
		return;
	}
	Insert_LinkNode(head, 0, data);
}
void PushBack_LinkNode(LLink *head, LinkNode *data)//尾插
{
	if (head == NULL || data == NULL)
	{
		return;
	}
	LinkList *temp = (LinkList *)head;
	Insert_LinkNode(head, temp->size, data);
}
LinkNode * RemoveByPos_LinkNode(LLink *head, int pos)//删除通过位置  
{
	if (head == NULL)
	{
		return NULL;
	}
	LinkList *temp = (LinkList *)head;
	if (pos < 0 || pos >= temp->size)//如果位置小于0或者 大于等于链表的长度返回
	{
		return NULL;
	}
	LinkNode *pCurrent = &(temp->header);
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	LinkNode *DelNode = pCurrent->next;//保存将要删除的节点
	pCurrent->next = DelNode->next;
	temp->size--;
	return DelNode;//返回要删除节点的位置
}
void RemoveByVal_LinkNode(LLink *head, LinkNode * data, TYPE_COMPARE compare)//通过值来删除 , 要用到一个比较的回调函数
{
	if (head == NULL || data == NULL || compare == NULL)
	{
		return;
	}
	LinkList *temp = (LinkList *)head;
	if (temp->size == 0)//如果链表为空 ,则直接返回
	{
		return;
	}

	LinkNode *pPrev = &(temp->header);
	LinkNode *pCurrent = temp->header.next;

	while (pCurrent)
	{
		if (compare(pCurrent, data))//如果是要删除的节点
		{
			pPrev->next = pCurrent->next;
			temp->size--;
			break;
		}
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
	if (pCurrent == NULL)
	{
		printf("没有找到要删除的数据\n");
	}
}
LinkNode * PopFront(LLink *head)//头删
{
	if (head == NULL)
	{
		return NULL;
	}
	return RemoveByPos_LinkNode(head, 0);
}

LinkNode * PopBack(LLink *head)//尾删
{
	if (head == NULL)
	{
		return NULL;
	}

	LinkList * temp = (LinkList *)head;

	return RemoveByPos_LinkNode(head, temp->size-1);
}
int GetLinkListLen(LLink *head)//获取链表长度
{
	if (head == NULL)
	{
		return 0;
	}
	LinkList *temp = (LinkList *)head;
	return temp->size;
}
void Destroy_LinkList(LLink *head)//销毁链表
{
	if (head == NULL)
	{
		return;
	}
	free(head);
	head = NULL;
}
void Foreach(LLink *head, TYPE_PRINT print)//遍历打印链表
{
	if (head == NULL || print == NULL)
	{
		return;
	}
	LinkList *temp = (LinkList *)head;
	LinkNode *pCurrent = temp->header.next;
	for (int i = 0; i < temp->size; i++)
	{
		print(pCurrent);
		pCurrent = pCurrent->next;
	}
}

以下是测试函数:

#include "LinkList.h"

typedef struct _Tag_Teacher
{
	LinkNode next;//保存下一个节点
	char name[64];
	int age;
}Teacher;

void print(LinkNode * data)//打印的函数
{
	if (data == NULL)
	{
		return;
	}
	Teacher * pT = (Teacher *)data;
	printf("name: %s       age:%d\n", pT->name, pT->age);
}
bool compare(LinkNode *p1, LinkNode *p2)//比较的回调函数
{
	if (p1 == NULL || p2 == NULL)
	{
		return false;
	}
	Teacher *pp1 = (Teacher *)p1;
	Teacher *pp2 = (Teacher *)p2;
	if ((strcmp(pp1->name, pp2->name) == 0) && (pp1->age == pp2->age))
	{
		return true;
	}
	return false;
}
void test()
{
	Teacher p1, p2, p3, p4, p5, p6;
	strcpy(p1.name, "aaa");
	strcpy(p2.name, "bbb");
	strcpy(p3.name, "ccc");
	strcpy(p4.name, "ddd");
	strcpy(p5.name, "eee");
	strcpy(p6.name, "fff");

	p1.age = 10;
	p2.age = 20;
	p3.age = 30;
	p4.age = 40;
	p5.age = 50;
	p6.age = 60;

	LLink *list = Init_LinkList();//获取链表的头
	Insert_LinkNode(list, 1, (LinkNode *)&p1);
	PushBack_LinkNode(list, (LinkNode *)&p2);
	Insert_LinkNode(list, 1, (LinkNode *)&p3);//40 10 30 20 50 60
 	PushFront_LinkNode(list, (LinkNode *)&p4);
	Insert_LinkNode(list, 100, (LinkNode *)&p5);
	Insert_LinkNode(list, -1, (LinkNode *)&p6);
	Foreach(list, print);
	printf("\n------------------------------------------------------\n");

	Teacher *t = NULL;
	t =(Teacher *)PopFront(list);
	printf("name: %s       age:%d\n", t->name, t->age);

	printf("\n**************************************************\n");
	PopBack(list);
	Foreach(list, print);
	printf("\n------------------------------------------------------\n");

	RemoveByPos_LinkNode(list, 1);

	RemoveByPos_LinkNode(list, 111);
	RemoveByVal_LinkNode(list, (LinkNode *)&p1, compare);
	Foreach(list, print);
	printf("\n------------------------------------------------------\n");
	int len = GetLinkListLen(list);
	printf("链表现在的长度是%d\n", len);
	Destroy_LinkList(list);
}
void main()
{
	test();
	system("pause");
}

以下是第二种通用链表,链表中保存指针域和数据域

头文件:

#ifndef LINKLIST_H
#define LINKLIST_H

#include<stdlib.h>

//链表节点
typedef struct _LINKNODE{
	void* data; //数据域
	struct _LINKNODE* next; //指针域
}LinkNode;

//链表
typedef struct _LINKLIST{
	LinkNode header; //头结点
	int size;//链表大小
}LList;

typedef void* LinkList;
//比较函数指针
typedef int(DATA_COMPARE)(void*, void*);
//打印函数指针
typedef void(DATA_PRINT)(void*);

//初始化
LinkList Init_LinkList();
//指定位置插入
void Insert_LinkList(LinkList list,int pos,void* data);
//头部插入操作
void PushFront_LinkList(LinkList list, void* data);
//尾部插入操作
void PushBack_LinkList(LinkList list, void* data);
//指定位置删除
void RemoveByPos_LinkList(LinkList list,int pos);
//头部删除操作
void PopFront_LinkList(LinkList list);
//尾部删除操作
void PopBack_LinkList(LinkList list);
//值删除
void RemoveByVal_LinkList(LinkList list, void* data, DATA_COMPARE compare);
//获得指定位置元素
void* Get_LinkList(LinkList list,int pos);
//链表大小
int Size_LinkList(LinkList list);
//遍历链表
void Print_LinkList(LinkList list, DATA_PRINT print);
//销毁链表
void Destroy_LinkList(LinkList list);


#endif

函数实现:

#include"LinkList.h"

//初始化
LinkList Init_LinkList(){
	LList* list = (LList*)malloc(sizeof(LList));
	list->size = 0;
	list->header.next = NULL;
	return list;
}
//指定位置插入
void Insert_LinkList(LinkList list, int pos, void* data){
	if (list == NULL){
		return;
	}
	if (data == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	//判断位置是否越界 位置从0开始,如果越界,默认插入到尾部
	if (pos < 0 || pos > mlist->size){
		pos = mlist->size;
	}

	//查找插入位置
	LinkNode* pCurrent = &(mlist->header);
	int i = 0;
	for (; i < pos;i++){
		pCurrent = pCurrent->next;
	}

	//创建新节点
	LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
	newnode->data = data;
	newnode->next = NULL;

	//新节点入链表
	newnode->next = pCurrent->next;
	pCurrent->next = newnode;
	mlist->size++;
}
//头部插入操作
void PushFront_LinkList(LinkList list, void* data){
	if (list == NULL){
		return;
	}
	if (data == NULL){
		return;
	}
	Insert_LinkList(list,0,data);
}
//尾部插入操作
void PushBack_LinkList(LinkList list, void* data){
	if (list == NULL){
		return;
	}
	if (data == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	Insert_LinkList(list, mlist->size, data);
}
//指定位置删除
void RemoveByPos_LinkList(LinkList list, int pos){
	if (list == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	if (pos < 0 || pos >= mlist->size){
		return;
	}
	//判断链表是否为空
	if (mlist->size == 0){
		return;
	}

	//查找删除节点的前一个节点
	LinkNode* pCurrent = &(mlist->header);
	int i = 0;
	for (; i < pos;i++){
		pCurrent = pCurrent->next;
	}
	//缓存待删除节点
	LinkNode* pDel = pCurrent->next;
	//重新连接被删除节点前驱和后继节点
	pCurrent->next = pDel->next;
	//释放被删除节点内存
	free(pDel);
	mlist->size--;
}
//头部删除操作
void PopFront_LinkList(LinkList list){
	if (list == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	if (mlist->size == 0){
		return;
	}
	RemoveByPos_LinkList(list, 0);
}
//尾部删除操作
void PopBack_LinkList(LinkList list){
	if (list == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	if (mlist->size == 0){
		return;
	}
	RemoveByPos_LinkList(list, mlist->size - 1);
}
//值删除
void RemoveByVal_LinkList(LinkList list, void* data, DATA_COMPARE compare){

	if (list == NULL){
		return;
	}
	if (data == NULL){
		return;
	}
	if (compare == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	if (mlist->size == 0){
		return;
	}

	//查找删除节点
	LinkNode* pPrev = &(mlist->header);
	LinkNode* pCurrent = pPrev->next;
	while (pCurrent != NULL){
		if (compare(pCurrent->data,data)){
			pPrev->next = pCurrent->next;
			//释放删除节点内存
			free(pCurrent);
			mlist->size--;
			break;
		}
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
	
}
//获得指定位置元素
void* Get_LinkList(LinkList list, int pos){

	if (list == NULL){
		return NULL;
	}
	LList* mlist = (LList*)list;
	if (pos < 0 || pos > mlist->size){
		return NULL;
	}

	//查找pos前一个位置的节点
	LinkNode* pCurrent = &(mlist->header);
	for (int i = 0; i < pos;i++){
		pCurrent = pCurrent->next;
	}

	return pCurrent->next->data;
}
//链表大小
int Size_LinkList(LinkList list){
	if (list == NULL){
		return -1;
	}
	LList* mlist = (LList*)list;
	return mlist->size;
}
//遍历链表
void Print_LinkList(LinkList list, DATA_PRINT print){	
	if (list == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	//赋值指针
	LinkNode* pCurrent = mlist->header.next;
	while (pCurrent!=NULL){
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}
//销毁链表
void Destroy_LinkList(LinkList list){
	if (list == NULL){
		return;
	}
	LList* mlist = (LList*)list;
	LinkNode* pCurrent = mlist->header.next;
	while (pCurrent != NULL){
		//缓存待删除节点下一个节点
		LinkNode* pNext = pCurrent->next;
		free(pCurrent);
		pCurrent = pNext;
	}

	//最后释放链表内存
	free(mlist);
	printf("链表内存释放!\n");
}

测试函数:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"LinkList.h"

typedef struct _PERSON{
	char name[64];
	int age;
}Person;


void MyPrint(void* data){
	Person* p = (Person*)data;
	printf("Name:%s Age:%d\n",p->name,p->age);
}

int MyCompare(void* data1,void* data2){
	Person* p1 = (Person*)data1;
	Person* p2 = (Person*)data2;
	return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

int main(){

	//初始化链表
	LinkList list = Init_LinkList();
	//创建数据
	Person p1 = { "aaa", 12 };
	Person p2 = { "bbb", 13 };
	Person p3 = { "ccc", 14 };
	Person p4 = { "ddd", 15 };
	Person p5 = { "eee", 16 };
	Person p6 = { "fff", 17 };
	//头插
	PushFront_LinkList(list, (void*)&p1);
	PushFront_LinkList(list, (void*)&p2);
	//尾插
	PushBack_LinkList(list, (void*)&p3);
	PushBack_LinkList(list, (void*)&p4);
	//指定位置插入
	Insert_LinkList(list, 2, (void*)&p5);
	//Insert_LinkList(list, 1, (void*)&p6);
	//打印
	Print_LinkList(list, MyPrint);
	//头删
	PopFront_LinkList(list);
	printf("头删结果:\n");
	Print_LinkList(list, MyPrint);
	printf("---------------------\n");
	//尾删
	PopBack_LinkList(list);
	printf("尾删结果:\n");
	Print_LinkList(list, MyPrint);
	printf("---------------------\n");
	//指定位置删除
	RemoveByPos_LinkList(list,1);
	printf("指定位置1删结果:\n");
	Print_LinkList(list, MyPrint);
	printf("---------------------\n");
	printf("链表长度:%d\n",Size_LinkList(list));
	//根据值删除
	RemoveByVal_LinkList(list, (void*)&p1, MyCompare);
	printf("根据值删结果:\n");
	Print_LinkList(list, MyPrint);
	printf("---------------------\n");
	//销毁链表
	Destroy_LinkList(list);

	system("pause");
	return EXIT_SUCCESS;
}




阅读更多
换一批

没有更多推荐了,返回首页