数据结构之单向链表

概述

    线性结构是一种最简单且常用的数据结构。线性结构的基本特点是节点之间满足线性关系。本章讨论的动态数组、链表、栈、队列都属于线性结构。他们的共同之处,是节点中有且只有一个开始节点和终端节点。按这种关系,可以把它们的所有节点排列成一个线性序列。但是,他们分别属于几种不同的抽象数据类型实现,它们之间的区别,主要就是操作的不同。线性表是零个或者多个数据元素的有限序列数据元素之间是有顺序的数据元素个数是有限的数据元素的类型必须相同


单向链表:线性表的链式存储结构中,每个节点中只包含一个指针域,这样的链表叫单链表。通过每个节点的指针域将线性表的数据元素按其逻辑次序链接在一起(如图)。


实现

LinkList.h

#ifndef LINKLIST_H
#define LINKLIST_H

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

//链表节点
typedef struct _LinkNode
{
	struct _LinkNode *next;
}LinkNode;

//链表
typedef struct _LinkList
{
	LinkNode header;
	int size;
}LinkList;

typedef void(DATA_PRINT)(LinkNode*);
typedef int(DATA_COMPARE)(LinkNode*, LinkNode*);

//初始化链表
int init_LinkList(void **list);
//指定位置插入
int insert_LinkList(void *list, int pos, void *data);
//头插
int PushFront_LinkList(void *list, void *data);
//尾插
int PushBack_LinkList(void *list, void *data);
//打印链表
int print_LinkList(void *list, DATA_PRINT* print);
//指定位置删除
int remove_bypos_LinkList(void *list, int pos);
//头部删除
int remove_PushFront_LinkList(void *list);
//尾部删除
int remove_PushBack_LinkList(void *list);
//根据值删除
int remove_byval_LinkList(void *list, void *data, DATA_COMPARE*compare);
//链表大小
int size_LinkList(void *list);
//销毁链表
int free_LinkList(void *list);


#endif


LinkList.c

#include"LinkList.h"

//初始化链表
int init_LinkList(void **list)
{
	if (NULL == list)
	{
		return -1;
	}
	LinkList *temp = (LinkList *)malloc(sizeof(LinkList));
	if (NULL == temp)
	{
		return -2;
	}
	temp->header.next = NULL;
	temp->size = 0;

	*list = temp;
	return 0;
}
//指定位置插入
int insert_LinkList(void *list, int pos, void *data)
{
	if (NULL == list)
	{
		return -1;
	}
	if (NULL == data)
	{
		return -2;
	}

	LinkList *temp = (LinkList *)list;

	if(pos < 0 || pos > temp->size)
	{
		pos = temp->size;
	}
	//辅助指针变量
	LinkNode *current = &(temp->header);
	for (int i = 0; i < pos; i++)
	{
		current = current->next;
	}
	//
	LinkNode * newnode = (LinkNode *)data;
	//新数据入链表
	newnode->next = current->next;
	current->next = newnode;
	temp->size++;

	return 0;
}
//头插
int PushFront_LinkList(void *list, void *data)
{
	insert_LinkList(list, 0, data);
	return 0;
}
//尾插
int PushBack_LinkList(void *list, void *data)
{
	LinkList *temp = (LinkList *)list;
	insert_LinkList(list, temp->size, data);
	return 0;
}


//打印链表
int print_LinkList(void *list, DATA_PRINT* print)
{
	if (NULL == list)
	{
		return -1;
	}
	if (NULL == print)
	{
		return -2;
	}
	LinkList *temp = (LinkList*)list;
	//辅助指针变量
	LinkNode* current = temp->header.next;
	while (NULL != current)
	{
		print(current);
		current = current->next;
	}

	return 0;
}
//指定位置删除
int remove_bypos_LinkList(void *list, int pos)
{
	if (NULL == list)
	{
		return -1;
	}
	LinkList *temp = (LinkList *)list;
	if (pos < 0 || pos >= temp->size)
	{
		return -2;
	}
	LinkNode *current = &(temp->header);
	for (int i = 0; i < pos; i++)
	{
		current = current->next;
	}
	//缓冲被删除节点
	LinkNode *pdel = current->next;
	//待删除节点前驱节点的后继指针指向待删除节点的后继节点
	current->next = pdel->next;
	temp->size--;

	return 0;
}
//头部删除
int remove_PushFront_LinkList(void *list)
{
	if (NULL == list)
	{
		return -1;
	}
	LinkList *temp = (LinkList *)list;
	if (temp->size == 0)
	{
		return -2;
	}
	remove_bypos_LinkList(list, 0);

	return 0;
}
//尾部删除
int remove_PushBack_LinkList(void *list)
{
	if (NULL == list)
	{
		return -1;
	}
	LinkList *temp = (LinkList *)list;
	if (temp->size == 0)
	{
		return -2;
	}
	remove_bypos_LinkList(list, temp->size - 1);

	return 0;
}
//根据值删除
int remove_byval_LinkList(void *list, void *data, DATA_COMPARE*compare)
{
	if (NULL == list)
	{
		return -1;
	}
	if (NULL == data)
	{
		return -2;
	}
	if (NULL == compare)
	{
		return -3;
	}
	LinkList *temp = (LinkList*)list;
	if (temp->size == 0)
	{
		return -1;
	}
	//辅助指针变量
	LinkNode *prev = &(temp->header);
	LinkNode *current = prev->next;
	while (current != NULL)
	{
		if (compare(current, data))
		{
			prev -> next = current->next;
			temp->size--;
			break;
		}
		prev = current;
		current = prev->next;
	}
	return 0;
}
//链表大小
int size_LinkList(void *list)
{
	if (NULL == list)
	{
		return -1;
	}
	LinkList *temp = (LinkList *)list;

	return temp->size;
}
//销毁链表
int free_LinkList(void *list)
{
	if (NULL == list)
	{
		return -1;
	}
	free(list);

	return 0;
}


测试代码

main.c

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

typedef struct _PERSON{
	LinkNode node;
	char name[64];
	int age;
}Person;
void print(LinkNode* curr)
{
	if (NULL == curr)
	{
		return;
	}
	Person *temp = (Person*)curr;
	printf("%s\t%d\n", temp->name, temp->age);

	return;
}
int compare(LinkNode* d1, LinkNode* d2)
{
	Person * p1 = (Person *)d1;
	Person * p2 = (Person *)d2;
	if (strcmp(p1->name, p2->name) == 0 && p1->age == p2->age)
	{
		return 1;
	}
	return 0;
}

int main()
{
	Person p1 = { NULL, "aaa", 10 };
	Person p2 = { NULL, "bbb", 20 };
	Person p3 = { NULL, "ccc", 30 };
	Person p4 = { NULL, "ddd", 40 };
	Person p5 = { NULL, "eee", 50 };
	Person p6 = { NULL, "fff", 60 };
	Person p7 = { NULL, "ggg", 70 };
	Person p8 = { NULL, "aaa", 10 };

	LinkList *list = NULL;
	init_LinkList(&list);
	insert_LinkList(list, 10, &p1);
	insert_LinkList(list, 10, &p2);
	insert_LinkList(list, 10, &p3);
	//打印链表
	print_LinkList(list, print);
	printf("********************************\n");
	//头插
	PushFront_LinkList(list, &p4);
	PushFront_LinkList(list, &p5);
	print_LinkList(list, print);
	printf("********************************\n");
	//尾插
	PushBack_LinkList(list, &p6);
	PushBack_LinkList(list, &p7);
	print_LinkList(list, print);
	printf("********************************\n");
	//指定位置删除
	remove_bypos_LinkList(list, 4);
	print_LinkList(list, print);
	printf("********************************\n");
	//头部删除
	remove_PushFront_LinkList(list);
	print_LinkList(list, print);
	printf("********************************\n");
	//尾部删除
	remove_PushBack_LinkList(list);
	print_LinkList(list, print);
	printf("********************************\n根据值删除\n");
	//根据值删除
	remove_byval_LinkList(list, &p8, compare);
	print_LinkList(list, print);
	printf("********************************\n");
	int len = size_LinkList(list);
	printf("链表大小:%d\n", len);
	//销毁链表
	free_LinkList(list);

	system("pause");
	return EXIT_SUCCESS;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值