顺序表、链表、栈、队列、二叉树、哈希表(二)

上一节中,我们介绍了线性表中的顺序表,接下来我们介绍一下线性表中的链表。

链表(单向链表、双向链表、单向循环链表、双向循环链表、静态表)

概念

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

单向链表

如下图所示

图中:2.3.4.5都是结构体,称之为结点,与顺序表不同的是,链表中的每个结点不是只单纯的存一个数据。而是一个结构体,结构体成员包括一个所存的数据,和下一个结点的地址。另外,顺序表中的地址是连续的,而链表中结点的地址是随机分配的。

直接上单项链表的底层实现代码:

LinkList.h

#ifndef LINK_LIST_H
#define LINK_LIST_H
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义单个节点的结构体
typedef struct LINK_NODE
{
	void* data;
	struct LINK_NODE* next;
} LINK_NODE;

//定义链表
typedef struct LINK_LIST
{
	struct LINK_NODE* head;
	int size;
} LINK_LIST;

typedef void(*PRINTLINKNODE)(void*);

//初始化链表
LINK_LIST* Init_LinkList();
//插入
void Pushback_LinkList(LINK_LIST* list, int pos, void* data);
//根据位置删除
void RemoveByPos_LinkList(LINK_LIST* list, int pos);
//查找
int Find_LinkList(LINK_LIST* list, void* data);
//打印
void Print_LinkList(LINK_LIST* list, PRINTLINKNODE print);
//释放
void Freespace_LinkList(LINK_LIST* list);
//清空数组
void Clear_LinkList(LINK_LIST* list);
//获得链表长度
int Size_LinkList(LINK_LIST* list);
//返回第一个节点
void* Front_LinkList(LINK_LIST* list);
#endif // !DYNAMIC_ARRAY_H

LinkList.cpp

#include"LinkList.h"
#include<iostream>
LINK_LIST* Init_LinkList()
{
	LINK_LIST* list = (LINK_LIST*)malloc(sizeof(LINK_LIST));
	list->size = 0;
	list->head = (LINK_NODE*)malloc(sizeof(LINK_NODE));
	list->head->data = NULL;
	list->head->next = NULL;
	return list;
}
//插入
void Pushback_LinkList(LINK_LIST* list, int pos, void* data)
{
	if (list == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}
	//如果pos越界,默认插在最后面
	if (pos > list->size || pos < 0)
	{
		pos = list->size;
	}
	//创建新结点
	LINK_NODE*newnode = (LINK_NODE*)malloc(sizeof(LINK_NODE));
	newnode->data = data;
	newnode->next = NULL;
	//创建辅助节点
	LINK_NODE* pCurrent = list->head;
	//找到节点位置
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	//插入
	newnode->next = pCurrent->next;
	pCurrent->next = newnode;
	list->size++;
}
//根据位置删除
void RemoveByPos_LinkList(LINK_LIST* list, int pos)
{
	if (list == NULL)
	{
		return;
	}
	if (pos > list->size || pos < 0)
	{
		return;
	}
	//创建辅助节点
	LINK_NODE* pCurrent = list->head;
	//找到节点位置
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	//缓存删除节点
	LINK_NODE* pDel = pCurrent->next;
	pCurrent->next = pDel->next;
	//释放缓存节点
	free(pDel);
	list->size--;

}
//查找
int Find_LinkList(LINK_LIST* list, void* data)
{
	if (list == NULL)
	{
		return -1;
	}
	if (data == NULL)
	{
		return -1;
	}
	LINK_NODE* pCurrent = list->head->next;
	int i = 0;
	while (pCurrent != NULL)
	{
		if (pCurrent->data == data)
		{
			break;
		}
		i++;
		pCurrent = pCurrent->next;
	}
	return i;
}
//打印
void Print_LinkList(LINK_LIST* list, PRINTLINKNODE print)
{
	if (list == NULL)
	{
		return;
	}
	LINK_NODE* pCurrent = list->head->next;
	while (pCurrent != NULL)
	{
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}
//释放
void Freespace_LinkList(LINK_LIST* list)
{
	if (list == NULL)
	{
		return;
	}
	LINK_NODE* pCurrent = list->head;
	while (pCurrent != NULL)
	{
		//缓存下一个结点
		LINK_NODE* pNext = pCurrent->next;
		free(pCurrent);
		pCurrent = pNext;
	}
	//释放链表内存
	free(list);
}
//获得链表长度
int Size_LinkList(LINK_LIST* list)
{
	return list->size;
}
//返回第一个节点
void* Front_LinkList(LINK_LIST* list)
{
	return list->head->next;
}

mian.cpp

#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 main()
{
	LINK_LIST* list = Init_LinkList();
	Person P1 = { "A",10 };
	Person P2 = { "B",20 };
	Person P3 = { "C",30 };
	Person P4 = { "D",40 };
	Person P5 = { "E",50 };
	Pushback_LinkList(list, 0, &P1);
	Pushback_LinkList(list, 0, &P2); 
	Pushback_LinkList(list, 0, &P3);
	Pushback_LinkList(list, 0, &P4);
	Pushback_LinkList(list, 0, &P5);

	Print_LinkList(list, MyPrint);
	Freespace_LinkList(list);
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值