基础数据结构(二)——(最全)单链表的实现

单链表

此文章看完理解透彻可能需要点时间,但是我相信你可以,记得收藏关注呦~

定义
每一个存储数据的结点,只能记录直接后继结点的位置。

一、带头结点的单链表
1、定义

有一个头结点,头结点的数据与不存储有效数据,只是使用其指针域指向第一个存储数据的结点。

2、图示:在这里插入图片描述
3、实现
(1)结构体的声明

typedef int ElemType;
typedef struct Node
{
	ElemType data;
	struct Node* next;
}LinkList;

(2)方法实现

void InitLinkList(LinkList*);//初始化
void InsertLinkList(LinkList*, ElemType, int);//插入
void InsertLinkListHead(LinkList*, ElemType);//头插
void InsertLinkListTail(LinkList*, ElemType);//尾插
void DeleteLinkList(LinkList*, int);//按位置删除
void DeleteLinkListHead(LinkList*);//头删
void DeleteLinkListTail(LinkList*);//尾删
void DeleteLinkListValue(LinkList* , ElemType);//按值删除
void ShowLinkList(LinkList *);//显示方法
void ClearLinkList(LinkList*);//清空数据
void DestroyLinkList(LinkList*);//销毁

(3)代码实现

//初始化
void InitLinkList(LinkList* list)
{
	if (list == NULL) exit(0);
	list->next = NULL;
}
//插入
void InsertLinkList(LinkList *list, ElemType val, int pos)
{
	if (list == NULL) exit(0);
	if (pos < 0)
	{
		printf("pos is error\n");
		return;
	}
	LinkList* p = list;
	//1、找到pos位置前的一个节点 2、如果pos超过length,则p肯定为NULL
	while (pos < 0 && p != NULL)
	{
		p = p->next;
		pos--;
	}
	if (p == NULL)
	{
		printf("pos is error\n");
		return;
	}
	LinkList* newNode = ApplyNode(val, p->next);
	if (newNode == NULL) return;
	p->next = newNode;
}
//静态方法
static LinkList* ApplyNode(ElemType val, LinkList* next)
{
	LinkList* s = (LinkList*)malloc(sizeof(LinkList));
	if (s == NULL) return NULL;
	s->data = val;
	s->next = next;
	return s;
}
//头插
void InsertLinkListHead(LinkList *list, ElemType val)
{
	if (list == NULL) exit(0);
	InsertLinkList(list, val, 0);
}
//尾插
void InsertLinkListTail(LinkList* list, ElemType val)
{
	if (list == NULL) exit(0);
	LinkList* p = list;
	while (p->next != NULL) p = p->next;
	LinkList* s = ApplyNode(val, NULL);
	if (s == NULL) return;
	p->next = s;
}
//按位置删除
void DeleteLinkList(LinkList *list, int pos)
{
	if (list == NULL) exit(0);	
	LinkList* p = list;
	while (pos && p->next != NULL)
	{
		p = p->next;
		pos--;
	}
	if (p->next == NULL) return;
	LinkList* q = p->next;
	p->next = q->next;
	free(q);
}
//头删
void DeleteLinkListHead(LinkList *list)
{
	if (list == NULL) exit(0);
	DeleteLinkList(list, 0);
}
//尾删
void DeleteLinkListTail(LinkList* list)
{
	if (list == NULL) exit(0);
	LinkList* p = list;
	LinkList* q = p->next;
	while (q != NULL && q->next != NULL)
	{
		p = p->next;
		q = q->next;
	}
	if (q == NULL) return;
	p->next = NULL;
	free(q);
}
//按值删除
void DeleteLinkListValue(LinkList *list, ElemType val)
{
	if (list == NULL) exit(0);
	LinkList* p = list;
	LinkList* q = p->next;
	while (q != NULL)
	{
		if (q->data == val)
		{
			p->next = q->next;
			free(q);
			q = p->next;
		}
		else
		{
			p = q;
			q = q->next;
		}
	}
}
//显示方法
void ShowLinkList(LinkList* list)
{
	if (list == NULL) exit(0);
	LinkList* p = list->next;
	while (p != NULL)
	{
		printf("%d-->", p->data);
		p = p->next;
	}
	printf("\n");
}
//清空数据
void ClearLinkList(LinkList* list)
{
	if (list == NULL) exit(0);
	while (list->next != NULL) DeleteLinkListHead(list);
}
//销毁数据
void DestroyLinkList(LinkList *list)
{
	if (list == NULL) exit(0);
	ClearLinkList(list);
}

二、头指针单链表
1、定义
只有一个结点指针,只用这个结点指针保存第一个数据结点的地址
2、图示
在这里插入图片描述
和带头点的单链表实现的区别:插入时为空链的特殊处理和删除第一个结点的特殊处理。

3、实现
(1)结构体声明

typedef int ElemType;
typedef struct Node
{
	ElemType data;
	struct Node* next;
}List;

(2)方法实现

void InitList(List **list);//初始化
void InsertList(List** list, ElemType val, int pos);//插入
void InsertListHead(List** list, ElemType val);//头插
void InsertListTail(List** list, ElemType val);//尾插
void DeleteList(List** list, int pos);//按位置删除
void DeleteListHead(List** list);//头删
void DeleteListTail(List** list);//尾删
void DeleteListValue(List** list, ElemType val);//按值删除
void ShowList(List** list);//显示方法
void DestroyList(List** list);//销毁

(3)代码实现

//初始化
void InitList(List **list)
{
	if (list == NULL) exit(0);
	*list = NULL;
}
//按位置插入
void InsertList(List** list, ElemType val, int pos)
{
	if (list == NULL) exit(0);
	if (pos < 0)
	{
		printf("Insert::pos is error\n");
		return;
	}
	if (pos == 0)
	{
		InsertListHead(list, val);
	}
	else
	{
		List* p = *list;
		while (pos > 1 && p != NULL)
		{
			p = p->next;
			pos--;
		}
		if (p == NULL)
		{
			printf("Insert::pos is error\n");
		}
		else
		{
			List* newNode = _ApplyNode(val, p->next);
			if (newNode == NULL) exit(0);
			p->next = newNode;
		}
	}
}
//静态方法申请新结点
static List* _ApplyNode(ElemType val, List* next)
{
	List* s = (List*)malloc(sizeof(List));
	if (s == NULL) return NULL;
	s->data = val;
	s->next = next;
	return s;
}
//头插
void InsertListHead(List** list, ElemType val)
{
	if (list == NULL) exit(0);
	List* newNode = _ApplyNode(val, *list);
	if (newNode == NULL) exit(0);
	*list = newNode;
}
//尾插
void InsertListTail(List** list, ElemType val)
{
	if (list == NULL) exit(0);
	if (*list == NULL)
	{
		InsertListHead(list, val);
		return;
	}
	List* p = *list;
	while (p->next != NULL)
	{
		p = p->next;
	}
	p->next = _ApplyNode(val, NULL);
}
//按位置删除
void DeleteList(List** list, int pos)
{
	if (list == NULL) exit(0);
	if (*list == NULL)
	{
		printf("List is Empty\n");
		return;
	}
	if (pos < 0)
	{
		printf("Delete::pos is error\n");
	}
	if (pos == 0)
	{
		DeleteListHead(list);
	}
	else
	{
		List* p = *list;
		while (pos > 1 && p->next != NULL)
		{
			p = p->next;
			pos--;
		}
		if (p->next == NULL)
		{
			printf("Delete::pos is error\n");
		}
		else
		{
			List* q = p->next;
			p->next = q->next;
			free(q);
		}
	}
}
//头删
void DeleteListHead(List** list)
{
	if (list == NULL) exit(0);
	if (*list == NULL)
	{
		printf("List is Empty\n");
		return;
	}
	List* p = *list;
	*list = p->next;
	free(p);
}
//尾删
void DeleteListTail(List** list)
{
	if (list == NULL) exit(0);
	if (*list == NULL)
	{
		printf("List is Empty\n");
		return;
	}
	//仅剩下一个节点时,调用头删
	if ((*list)->next == NULL)
	{
		DeleteListHead(list);
		return;
	}
	List *p = *list;
	List *q = p->next;
	while (q->next != NULL)
	{
		p = q;
		q = q->next;
	}
	p->next = NULL;
	free(q);
}
//按值删除
void DeleteListValue(List** list, ElemType val)
{
	if (list == NULL) exit(0);
	if (*list == NULL) return;
	if((*list)->data == val)
	{
		DeleteListHead(list);
		DeleteListValue(list, val);
	}
	else
	{
		List* p = *list;
		List* q = p->next;
		while (q != NULL)
		{
			if (q->data == val)
			{
				p->next = q->next;
				free(q);
				q = p->next;
			}
			else
			{
				p = q;
				q = q->next;
			}
		}
	}
}
//显示方法
void ShowList(List** list)
{
	if (list == NULL) exit(0);
	List* p = *list;
	while (p != NULL)
	{
		printf("%d-->", p->data);
		p = p->next;
	}
	printf("NULL\n");
}
//销毁
void DestroyList(List** list)
{
	if (list == NULL) exit(0);
	while (*list != NULL)
	{
		DeleteListHead(list);
	}
}

总结:

1、链表存储数据时,在逻辑上时连续的,但是在物理空间上不连续。既然在物理空间上不连续,那么就不能使用下标来访问链表中的结点。
2、链表的查找需要遍历,且必须从头遍历。

在平时编写代码的时候,我们应该要注意编程的规范,才回保证我们的系统稳定运行。一本《高质量C/C++编程指南》介绍给大家。

此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~
技术之路不在一时,山高水长,纵使缓慢,驰而不息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值