C语言不带头结点的单链表

C语言不带头结点的单链表

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct node {
	struct node* next;
	int data;
} Lnode, * LinkList;

//初始化(不带头节点的单链表)
//如果头指针不是空,则置为空
void initSingleLinkList(Lnode* head) {
	if (head)
	{
		head = NULL;
	}
}

//链表的销毁(不带头节点的单链表)
void destroy(Lnode* L) {
	Lnode* p;
	while (L != NULL)
	{
		p = L;
		L = L->next;
		free(p);
	}
}

//清空链表中所有的元素
void clear(Lnode* L) {
	Lnode* p = L->next;
	Lnode* q;
	while (p != NULL)
	{
		q = p;
		p = p->next;
		free(q);
	}
	L->data = NULL;
	L->next = NULL;
}

//不带头节点的单链表,头插法
void headInsert(LinkList* L, int e) {
	Lnode* pNode = (Lnode*)malloc(sizeof(Lnode));
	pNode->data = e;
	pNode->next = *L;
	*L = pNode;	
}

//不带头节点的单链表,尾插法
//这里是通过遍历链表到最后一个节点,然后在最后一个节点后面插入新的节点
//也可以通过维护一个尾指针,直接利用尾指针插入新的节点,再维护尾指针
void tailInsert(LinkList* L, int e) {

	Lnode* pNode = (Lnode*)malloc(sizeof(Lnode*));
	pNode->data = e;
	pNode->next = NULL;

	if (!L)
	{
		*L = pNode;
	}
	else
	{
		Lnode* p = *L;
		while (p->next)
		{
			p = p->next;
		}
		p->next = pNode;
	}
}

//链表的遍历输出
void show(Lnode* L) {
	if (!L)
	{
		printf("L为空\n");
		return;
	}
	else
	{
		
		Lnode* p = L;
		int i = 0;
		while (p)
		{
			printf("链表中的第%d个元素是%d\n", i++, p->data);
			p = p->next;
		}
	}
}

//判断链表是否包含某个元素
bool contains(Lnode* L, int e) {
	if (!L)
	{
		return false;
	}
	else
	{
		Lnode* p = L;
		while (p)
		{
			if (p->data == e) {
				return true;
			}
			p = p->next;
		}
		return false;
	}
}

//删除链表中的某个元素(第一次出现的目标元素节点)
bool delete(Lnode* L, int e) {
	if (!L)
	{
		return false;
	}
	else if (L->data == e)
	{
		L = L->next;
	}
	else
	{
		Lnode* p = L->next;
		Lnode* q = L;
		while (p)
		{
			if (p->data == e)
			{
				q->next = p->next;
				free(p);
				return true;
			}
			q = p;
			p = p->next;
		}
	}
}

//删除第i个位置的节点,返回删除节点的数据域
bool deleteIndex(LinkList* L, int index,int* e) {
	if (! (*L) || index < 0)
	{
		*e = -1;
		return false;
	}
	//如果删除的是首元节点,首元节点后无节点,则链表为空,有节点,则下一个节点为首元节点
	if (*L && index == 0) {
		if (!(*L)->next)
		{
			*e = (*L)->data;
			free(L);
			return true;
		}
		else
		{
			*e = (*L)->data;
			Lnode* p = (*L);
			(*L) = (*L)->next;
			free(p);
			return true;
		}
	}
	
	//如果删除的是中间的普通节点,则需要将该节点的前驱节点的next指向该节点的后一个节点
	Lnode* p = *L;
	int i = 0;
	while (p->next)
	{
		if (i == index-1)
		{
			*e = p->next->data;
			p->next = p->next->next;
			return true;
		}
		i++;
		p = p->next;
	}
	*e = -1;
	return false;
	//如果删除的是尾节点,则不需要将尾节点的前一个节点的next域指向尾节点的后一个节点
}

//链表中元素的个数
int  size(Lnode* L) {
	if (!L)
	{
		Lnode* p = L;
		int i = 0;
		while (!p)
		{
			i++;
			p = p->next;
		}
		return i;
	}
	return -1;
}

//链表的逆序
Lnode* reversedAtNode(LinkList* head, Lnode* pNode) {
	if (pNode->next == NULL)
	{
		*head = pNode;
	}
	else
	{
		(reversedAtNode(head, pNode->next))->next = pNode;
		pNode->next = NULL;
	}
	return pNode;
}
void reversed(LinkList* L) {
	if (size(L) == 0)
	{
		return;
	}
	reversedAtNode(L, *L);
}

void main() {
	Lnode* head = NULL;
	initSingleLinkList(head);
	for (int i = 0; i < 5; i++)
	{
		headInsert(&head, i);
	}
	show(head);

	for (int i = 5; i < 10; i++)
	{
		tailInsert(&head, i);
	}
	show(head);

	//判断链表中是否包含元素e
	if (contains(head, 3)) {
		printf("包含元素%d\n", 3);
	}
	else
	{
		printf("不包含元素%d\n", 3);
	}

	//删除第一次出现在链表中的元素为e的节点
	printf("测试删除==========\n");
	delete(head, 3);
	show(head);

	//删除链表中第index的元素,返回数据与
	printf("测试删除第index的节点==========\n");
	int resDel;
	deleteIndex(&head, 8, &resDel);
	printf("被删除的是%d\n", resDel);
	show(head);

	//测试链表的逆转
	printf("测试链表的逆转=======\n");
	show(head);
	printf("=================start\n");
	reversed(&head);
	show(head);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值