数据结构之单链表的基本操作-C语言实现

本文介绍了使用C语言实现单链表的基本操作,包括初始化、头插法、尾插法、在指定位置插入和删除结点等,并探讨了不同操作的时间复杂度,如O(1)和O(n)的实现方式。

数据结构复习之单链表的基本操作--C语言实现

#include<stdio.h>
#include<stdlib.h>
/*
* 默认带头结点
* 1.单链表定义
* 2.头插法
* 3.尾插法
* 4.在指定位置插入一个结点  tips:可以封装在p结点之后插入一个结点
* 5.在某结点之前插入一个结点 --->  O(n)和O(1)实现方式
* 6.在某结点之后插入一个结点 
* 7.删除指定结点   ---> O(n)和O(1)实现方式
*/
typedef int ElemType;
//1.单链表定义
typedef struct LNode
{
	ElemType data;
	struct LNode* next;
}LNode, *LinkList;
//初始化
void InitLinkList(LinkList *L)
{
	*L = (LinkList)malloc(sizeof(LNode));
	(*L)->next = NULL;
}
//2.头插法
LinkList List_HeadInsert(LinkList L,LNode *node)
{
	//1.若待插入结点是null,则不插入,直接返回L
	if (node == NULL)
	{
		return L;
	}
	node->next = L->next;
	L->next = node;
	return L;
}
//3.尾插法
LinkList List_TailInsert(LinkList L, LNode* node)
{
	//1.若待插入结点是null,则不插入,直接返回L
	if (node == NULL)
	{
		return L;
	}
	LNode* p = L;
	//2.寻找单链表尾部
	while (p->next != NULL)
	{
		p = p->next;
	}
	//3.讲新结点加入到链表尾部
	p->next = node;
	return L;
}
void PrintLinkList(LinkList L)
{
	LNode* p = L->next;
	while (p != NULL)
	{
		printf("%d,",p->data);
		p = p->next;
	}
	printf("\n");
}
//返回第i个结点
LNode* getNode(LinkList L, int index)
{
	if (index < 0)
	{
		return NULL;
	}
	else
	{
		int j = 0;   //指示当前第几个结点
		LNode* p = L;
		//寻找第index结点
		while (p != NULL && j < index)
		{
			p = p->next;
			++j;
		}
		return p;
	}
}
//4.在指定位置插入一个结点
bool ListInsert(LinkList L, int index, ElemType e)
{
	if (index < 1)
	{
		return false;
	}
	LNode* p = NULL;
	//先寻找第index-1结点
	p = getNode(L, index - 1);
	//若p是null,说明index大于length+1,也就是说传入了不合法的位序index,直接return false
	if (p == NULL)
	{
		return false;
	}
	//找到第index-1结点后,将新结点结点追加到它后面
	LNode* q = (LNode*)malloc(sizeof(LNode));
	q->data = e;
	q->next = p->next;
	p->next = q;
	return true;
}
//5.在某结点之前插入一个结点
//5.1知道单链表头结点,在node前插入一个新结点。时间复杂度是O(n)
bool ListInsertBefore(LinkList L, int index, ElemType e)
{
	if (index < 1)
	{
		return false;
	}
	//先获取第index-1结点
	LNode* p = getNode(L,index-1);
	if (p == NULL)
	{
		return false;
	}
	LNode* q = (LNode*)malloc(sizeof(LNode));
	q->data = e;
	q->next = p->next;
	p->next = q;
	return true;
}
//5.2不知道单链表头结点,希望在node前插入一个新结点q
//可以先将新结点插入到node后面,然后交换node和q的data即可(在node前插入的逻辑上是对的),时间复杂度是O(1)
bool ListInsertBefore2(LNode* node, ElemType e)
{
	if (node == NULL)
	{
		return false;
	}
	//将新结点q插入到node的后面
	LNode* q = (LNode*)malloc(sizeof(LNode));
	q->next = node->next;
	node->next = q;
	//然后交换node和新结点q的data
	q->data = node->data;;
	node->data = e;
	return true;
}
//6.在某结点后面插入一个结点
bool ListInsertAfter(LinkList L, LNode* node, ElemType e)
{
	if (node == NULL)
	{
		return false;
	}
	LNode* q = (LNode*)malloc(sizeof(LNode));
	q->data = e;
	q->next = node->next;
	node->next = q;
	return true;
}
//7.删除结点
//7.1删除第index结点,时间复杂度是O(n)
bool ListDelete(LinkList L, int index, ElemType* e)
{
	if (index < 1)
	{
		return false;
	}
	LNode* p = getNode(L, index - 1);
	if(p == NULL)
	{
		return false;
	}
	LNode* node = p->next;  //node是被删除的结点
	p->next = node->next;   //node的前驱指向node的后继
	free(node);             //释放node
	return true;
}
//7.2删除node,可以先将node的data修改为node1后继的data再删除node的后继,逻辑上也实现了删除node
//但是当删除单链表尾部元素时,将出错。因为尾部已经是最后一个元素,不存在后继,或者说它的后继是NULL
//时间复杂度是O(1)
bool ListDelete2(LNode *node, ElemType* e)
{
	if (node == NULL)
	{
		return false;
	}
	LNode* p = node ->next;
	if (p == NULL)
	{
		return false;
	}
	node->data = p->data;  //将node的data修改为node后继的data
	node->next = p->next;  //node指向node后继的后继
	free(p);             //释放node的后继
	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值