初夏小谈:单链表的增/删/查/改操作(完整版)

链表谈到它我就想起了小时候吃的一种糖(我们把它叫链子糖)。它虽然总是会黏在牙齿上,但超甜的,让我们既爱又恨,所以总会联想起它。

哈哈^_^.......

回到正文今天的链表。这次是第一次完整的写一个链表。链表的思想简单,但真的自己一个一个实现还是遇到了不少的问题。其中一个重大的错误就是我经常会拿着指向头指针的指针去修改链表,这样会导致的链表不是想要的。犯这样的错误在于我总以为传值(传的是指向头指针的指针)以为它不会影响头指针。咳咳咳。还有就是对链表结点进行操作时(往往要存要操作的结点的前一个结点),由于要考虑内存泄漏,考虑不周会将结点指向搞错。导致有时代码看着没错误,但就是不是想要的结果。

完整代码:

#include "LinkList.h"

//1.创建链表结点
LinkListNode* CreateLinkListNode(DataType data)
{
	LinkListNode* NewNode = (LinkListNode*)malloc(sizeof(LinkListNode));
	assert(NewNode);
	NewNode->data = data;
	NewNode->next = NULL;
	return NewNode;
}

//2.初始化链表
void InitLinkList(LinkList* first)
{
	assert(first);
	first->head = NULL;
}

//3.销毁链表
void DestoryLinkList(LinkList* first)
{
	assert(first);
	LinkListNode* ptr = first->head;
	for (; first->head != NULL; first->head = first->head->next)
	{
		ptr = ptr->next;
		free(first->head);
		first->head = ptr;
	}
}

//4.查找链表结点(不管重复多少只返回遇到的第一个要查询的数据位置)
LinkListNode* FindLinkList(LinkList* first, DataType data)
{
	assert(first);
	LinkListNode* ptr = first->head;
	for (; ptr->next != NULL; ptr = ptr->next)
	{
		if (ptr->data == data)
		{
			return ptr;
		}
	}
	return ptr;
}

//5.增加结点
//5.1.头插
void HeadAddLinkList(LinkList* first, DataType data)
{
	assert(first);
	//创建一个结点
	LinkListNode* NewNode = CreateLinkListNode(data);
	assert(NewNode);
	if (first->head != NULL)
	{
		NewNode->next = first->head;
		first->head = NewNode;
	}
	else
	{
		first->head = NewNode;
	}
}

//5.2.尾插
void WeiChaLinkList(LinkList* first, DataType data)
{
	assert(first);
	if (first->head == NULL)
	{
		HeadAddLinkList(first, data);
		return;
	}
	LinkListNode* NewNode = CreateLinkListNode(data);
	assert(NewNode);
	LinkListNode* ptr = first->head;
	//通过循环找到最后一个结点
	for (; ptr->next != NULL; ptr = ptr->next)
	{
	}
	ptr->next = NewNode;
}

//5.3.任意pos位置插入(pos位置代表第N个结点)(从1开始)(pos是结点地址
void RenYiChaLinkList(LinkList* first, LinkListNode* pos, DataType data)
{
	assert(pos);
	LinkListNode* NewNode = CreateLinkListNode(data);
	assert(NewNode);
	NewNode->next = pos->next;
	pos->next = NewNode;
}

//6.删除结点
//6.1.头删
void HeadDelLinkList(LinkList* first)
{
	assert(first);
	if (first->head == NULL)
	{
		return;
	}
	LinkListNode* ptr = first->head->next;
	free(first->head);
	first->head = ptr;
}

//6.2.尾删
void WeiShanLinkList(LinkList* first)
{
	assert(first);
	if (first->head == NULL)
	{
		return;
	}
	LinkListNode* ptr = first->head;
	LinkListNode* ptr1 = NULL;
	for (; ptr->next != NULL; ptr = ptr->next)
	{
		ptr1 = ptr;
	}
	free(ptr1->next);
	ptr1->next = NULL;
}

//6.3.任意pos位置删除结点
//6.3.1.按位置删除
void RenYiWeiZhiDelLinkList(LinkList* first, LinkListNode* pos)
{
	assert(first);
	assert(pos);
	LinkListNode* ptr = first->head;
	if (ptr == NULL)
	{
		return;
	}
	if (ptr == pos)
	{
		HeadDelLinkList(first);
		return;
	}
	while (1)
	{
		if (ptr->next == pos)
		{
			LinkListNode* ptr1 = ptr->next->next;//标记要删除的结点位置
			free(ptr->next);
			ptr->next = ptr1;
			return;
		}
		else
		{
			if (ptr->next != NULL)
			{
				ptr = ptr->next;
			}
			else
			{
				return;
			}
		}
	}
}

//6.3.2.按数据删除
void RenYiDataDelLinkList(LinkList* first, DataType data)
{
	assert(first);
	LinkListNode* ptr = first->head;
	if (first->head == NULL)
	{
		return;
	}
	if (ptr->data == data)
	{
		HeadDelLinkList(first);
		return;
	}
	while (1)
	{
		if (ptr->next == NULL)
		{
			return;
		}
		else
		{
			if (ptr->next->data == data)
			{
				LinkListNode* ptr1 = ptr->next->next;
				free(ptr->next);
				ptr->next = ptr1;
			}
			else
			{
				ptr = ptr->next;
			}
		}
	}
}

//7.修改链表结点数据
void UpdateLinkList(LinkList* first, LinkListNode* pos, DataType data)
{
	assert(pos);
	LinkListNode* ptr = first->head;
	while (1)
	{
		if (ptr != pos)
		{
			if (ptr == NULL)
			{
				return;
			}
			ptr = ptr->next;
		}
		else
		{
			ptr->data = data;
			return;
		}
	}
}

//8.打印链表
void PintLinkList(LinkList* first)
{
	assert(first);
	LinkListNode* ptr = first->head;
	if (ptr == NULL)
	{
		printf("空链表\n");
		return;
	}
	while (1)
	{
		if (ptr != NULL)
		{
			printf("%d ", ptr->data);
			ptr = ptr->next;
		}
		else
		{
			printf("\n");
			return;
		}
	}
}
#pragma once

#include<stdio.h>
#include<assert.h>
#include<malloc.h>

//定义链表类
#define DataType int

typedef struct LinkListNode
{
	DataType data;
	struct LinkListNode* next;
}LinkListNode;

//定义头指针
typedef struct LinkList
{
	LinkListNode* head;
}LinkList;

//1.创建链表结点
LinkListNode* CreateLinkListNode(DataType data);

//2.初始化链表
void InitLinkList(LinkList* first);

//3.销毁链表
void DestoryLinkList(LinkList* first);

//4.查找链表结点
LinkListNode* FindLinkList(LinkList* first, DataType data);

//5.增加结点
//5.1.头插
void HeadAddLinkList(LinkList* first, DataType data);

//5.2.尾插
void WeiChaLinkList(LinkList* first, DataType data);

//5.3.任意pos位置后插入
void RenYiChaLinkList(LinkList* first, LinkListNode* pos, DataType data);

//6.删除结点
//6.1.头删
void HeadDelLinkList(LinkList* first);

//6.2.尾删
void WeiShanLinkList(LinkList* first);

//6.3.任意pos位置删除结点
//6.3.1.按位置删除
void RenYiWeiZhiDelLinkList(LinkList* first, LinkListNode* pos);

//6.3.2.按数据删除
void RenYiDataDelLinkList(LinkList* first, DataType data);

//7.修改链表结点数据
void UpdateLinkList(LinkList* first, LinkListNode* pos, DataType data);

//8.打印链表
void PintLinkList(LinkList* first);

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

void LinkListTest()
{
	LinkList* first = (LinkList*)malloc(sizeof(LinkList));
	InitLinkList(first);
	//头插
	HeadAddLinkList(first, 5);
	HeadAddLinkList(first, 4);
	HeadAddLinkList(first, 3);
	HeadAddLinkList(first, 2);
	HeadAddLinkList(first, 1);
	PintLinkList(first);
	
	//尾插
	WeiChaLinkList(first, 6);
	WeiChaLinkList(first, 7);
	WeiChaLinkList(first, 8);
	WeiChaLinkList(first, 9);
	WeiChaLinkList(first, 10);
	PintLinkList(first);
	
	//任意数据位置后插入
	LinkListNode* ptr = FindLinkList(first, 10);
	RenYiChaLinkList(first, ptr, 12);
	PintLinkList(first);

	//头删
	HeadDelLinkList(first);
	PintLinkList(first);

	//头插
	HeadAddLinkList(first, 1);
	PintLinkList(first);
	//尾删
	WeiShanLinkList(first);
	PintLinkList(first);

	//任意结点位置删除
	LinkListNode* ptr1 = FindLinkList(first, 1);
	RenYiWeiZhiDelLinkList(first, ptr1);
	PintLinkList(first);

	//任意数据删除
	RenYiDataDelLinkList(first, 10);
	PintLinkList(first);

	//修改链表中结点数据
	LinkListNode* ptr2 = FindLinkList(first, 2);
	UpdateLinkList(first, ptr2, 1);
	PintLinkList(first);
}

int main()
{
	LinkListTest();
	system("pause");
	return 0;
}

最后,我在实现链表的时候,是先实现函数声明,再去一步步完成它的实现。这样不至于使自己思路混乱。

                                                                                                                                                                              珍&源码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值