0
点赞
收藏
分享

微信扫一扫

数据结构 (三) 线性表_单向链表

禾木瞎写 2022-04-21 阅读 65

文章目录

一. 链表的定义

① 基本概念

② 单链表

在这里插入图片描述

③ 概念解释

  • 表头节点

  • 数据节点

  • 尾节点

在这里插入图片描述

④ 优缺点

优点

缺点

注意:

单向链表创建头文件 LinkList.h

#ifndef LINKLIST_H
#define LINKLIST_H
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// 要注意,链表本身有结构体,然后链表的节点也是一个结构体

// 链表节点
typedef struct LINKNODE
{
	void *data; // 指向任何数据类型
	struct LINKNODE *next; // 指向下一个节点
} LinkNode;

// 链表结构体
typedef struct LINKLIST
{
	LinkNode *head;
	int size; // 链表的大小
} LinkList;

// 打印函数指针
typedef void(*PRINT_PTR)(void *);

// 初始化链表
LinkList *init_linkList();

// 指定位置插入
void insert_linkList(LinkList *list, int pos, void *data);

// 删除指定位置的值
void remove_by_pos_linkList(LinkList *list, int pos);

// 获取链表的长度
int get_size_linkList(LinkList *list);

// 查找,根据数据进行查找
int find_linkList(LinkList *list, void *data);

// 返回第一个节点
void *front_linkList(LinkList *list);

// 打印链表节点
void print_linkList(LinkList *list,PRINT_PTR print);

// 释放链表内存
void free_space_linkList(LinkList *list);


#endif // !LINKLIST_H

实现

#include "LinkList.h"

// 初始化链表
LinkList *init_linkList()
{
	LinkList *list = (LinkList *)malloc(sizeof(LinkList));
	if (list != NULL)
	{
		list->size = 0;
		// 初始化头结点,头结点是不保存数据信息的
		list->head = (LinkNode *)malloc(sizeof(LinkNode));
		if (list->head != NULL)
		{
			list->head->data = NULL;
			list->head->next = NULL;
			return list;
		}
	}
	return NULL;
}

// 指定位置插入
void insert_linkList(LinkList *list, int pos, void *data)
{
	// 插入元素,指定位置插入,链表的位置序号,从头结点开始,索引是0,后面累加
	if (list == NULL || data == NULL)
	{
		return;
	}
	// 下标越界的友好处理,如果下标越界,就放到链表的尾部
	if (pos < 0 || pos > list->size)
	{
		pos = list->size;
	}
	// 创建新的节点
	LinkNode *newNode = (LinkNode *)malloc(sizeof(LinkNode));
	if (newNode == NULL)
	{
		return;
	}
	newNode->data = data;
	newNode->next = NULL;

	// 找节点 辅助指针变量
	LinkNode *pCurrent = list->head;
	// 一开始指向头结点,则遍历到pos-1次以后,指向的位置就是pos的前一个节点
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next; // 寻找下一个节点
	}
	// 循环结束之后pCurrent指向的节点位置是pos-1位置,现在是pos位置插入新的节点.
	// 相当于是在pos位置插入一个节点
	// 先将新节点,指向原来的pos位置
	newNode->next = pCurrent->next;
	// 然后是pos位置的前一个位置,指向新节点
	pCurrent->next = newNode;
	// 链表的长度加1
	list->size++;
}

// 删除指定位置的值
void remove_by_pos_linkList(LinkList *list, int pos)
{
	if (list == NULL)
	{
		return;
	}
	if (list != NULL)
	{
		if (pos < 0 || pos >= list->size)
		{
			return;
		}
		// 查找删除节点的前一个节点,注意head不是数据节点,所以遍历多少次,指向的就是那个位置的节点
		LinkNode *pCurrent = list->head;
		for (int i = 0; i < pos; i++)
		{
			pCurrent = pCurrent->next;
		}
		// 缓存删除的节点
		LinkNode *pDel = pCurrent->next;
		pCurrent->next = pDel->next;
		// 释放删除节点的内存
		free(pDel);
		list->size--;
	}
	return;
}

// 获取链表的长度
int get_size_linkList(LinkList *list)
{
	if (list != NULL)
	{
		return list->size;
	}
	return -1;
}

// 查找,根据数据的值进行查找,返回节点的位置
int find_linkList(LinkList *list, void *data)
{
	if (list != NULL && data != NULL)
	{
		LinkNode *pCurrent = list->head->next;
		int i = 0;
		while (pCurrent != NULL)
		{
			if (pCurrent->data == data)
			{
				break;
			}
			pCurrent = pCurrent->next;// 节点移动
			i++;
		}
		return i;
	}
}

// 返回第一个节点的数据
void *front_linkList(LinkList *list)
{
	if (list != NULL)
	{
		return list->head->next->data;
	}
	return NULL;
}

// 打印链表节点
void print_linkList(LinkList *list, PRINT_PTR print)
{
	if (list == NULL)
	{
		return;
	}
	// 辅助指针变量
	LinkNode *pCurrent = list->head->next;
	while (pCurrent != NULL)
	{
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}

// 释放链表内存
void free_space_linkList(LinkList *list)
{
	if (list != NULL)
	{
		LinkNode *pCurrent = list->head;
		while (pCurrent != NULL)
		{
			// 缓存下一个节点
			LinkNode *pNext = pCurrent->next;
			free(pCurrent);
			pCurrent = pNext;
		}
		// 释放链表内存
		free(list);
	}
	return;
}

测试

#include "LinkList.h"
typedef struct PERSON
{
	char name[64];
	int age;
	int score;
} Person;

// 打印函数
void my_print(void *data)
{
	Person *p = (Person *)data;
	printf("Name:%s Age:%d Score:%d \n", p->name, p->age, p->score);
}
int main()
{
	// 创建链表
	LinkList *list = init_linkList();

	// 创建数据
	Person p1 = { "aaaa",29,100 };
	Person p2 = { "bbbb",28,90 };
	Person p3 = { "cccc",27,80 };
	Person p4 = { "dddd",26,70 };
	Person p5 = { "eeee",25,60 };
	Person p6 = { "ffff",24,50 };

	// 数据插入链表,头部插入
	insert_linkList(list, 0, &p1);
	insert_linkList(list, 0, &p2);
	insert_linkList(list, 0, &p3);
	insert_linkList(list, 0, &p4);
	insert_linkList(list, 0, &p5);
	insert_linkList(list, 0, &p6);

	print_linkList(list, my_print);

	// 删除3
	remove_by_pos_linkList(list, 3);
	printf("**********************************\n");
	print_linkList(list, my_print);

	// 返回第一个节点
	printf("查找结果-------------------------------------\n");
	Person *ret = (Person *)front_linkList(list);
	printf("Name:%s,Age:%d,Score:%d\n", ret->name, ret->age, ret->score);

	// 销毁链表
	free_space_linkList(list);

	return 0;
}
举报

相关推荐

0 条评论