C语言数据结构之单链表

单链表的结构

     单链表的结构其实就是一个连续的结构体,可以把这个结构体看成一个一室一厅的房子,卧室放要存储的数据,餐厅放指向下一个房子的指针(其实就是下一个房子的地址)。链表通过访问指针去找到下一个链表,构成一个线性结构。

      链表可分为带(不带)哨兵位头结点,循环与非循环链表,以下演示非循环不带哨兵位的链表

接口函数

//尾插
void SListPushBack(SLTNode** pphead, SListDataType x);
//打印链表
void SListPrint(SLTNode* phead);
//头插
void SListPushFront(SLTNode** pphead, SListDataType x);
//尾删
void SListPopBack(SLTNode** pphead);
//头删
void SListPopFront(SLTNode** pphead);
//寻找链表当中的元素
SLTNode* SListFind(SLTNode* phead,SListDataType x);
//pos位置之前插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SListDataType x);
//删除指定元素
void SListRemoveElement(SLTNode** pphead, SListDataType x);
//pos位置之后插入
void SListInsertAfter(SLTNode** pphead, SLTNode* pos, SListDataType x);

接口函数的实现

(其中SLTNode*plist只是一个指针用来存储头结点的地址,可以认为*pphead就是头结点的地址)

typedef int SListDataType;
//定义一个结构体
typedef struct SListNode
{
	SListDataType data;
    //用来存储下一个节点的地址
	struct SListNode* next;
}SLTNode;
//创建链表
SLTNode* BuySListNode(SListDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("newnode");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//为什么传二级指针:因为我在main函数当中定义的是SLTNode*plist=NULL;定义了一个结点的地址,而我要改变 结点所存储的内容,在main函数当中传参就要&plist才能改变plist里存储的内容,plist是一级指真,&plist就要用二级指针来接受
void SListPushBack(SLTNode** pphead, SListDataType x)    
{
	SLTNode* newnode = BuySListNode(x);
	//不能写成*pphead->next,因为这时访问越界;
    
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

void SListPrint(SLTNode* phead)
{
	//assert(phead->next != NULL);
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL");
	printf("\n");
}
void SListPushFront(SLTNode** pphead, SListDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

void SListPopBack(SLTNode** pphead)
{
	//if (*pphead == NULL)
	//{
	//	return -1;
	//}
	assert(*pphead != NULL);
//链表当中就一个数据
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;
//找尾结点,以及尾结点的前一个
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
		tail = NULL;

	}
}

void SListPopFront(SLTNode** pphead)
{
	assert(*pphead!=NULL);
//找到头结点的下一个节点
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}
SLTNode* SListFind(SLTNode* phead,SListDataType x)
{
	SLTNode* find = phead;
	while (find != NULL)
	{
		if (find->data == x)
		{
			return find;
		}
		find = find->next;
	}
	return NULL;
}
//pos位置之前去插入
void SListInsert(SLTNode** pphead,SLTNode*pos, SListDataType x)
{
	assert(pos != NULL);
	if (pos == *pphead)
	{
		
		SLTNode* newnode = BuySListNode(x);
		newnode->next = *pphead;
		*pphead = newnode;

	}

	else
	{
		SLTNode* prev = *pphead;
//找pos位置前一个节点
	while ((prev)->next != pos)
	{
		prev = prev->next;
	}
	SLTNode* newnode = BuySListNode(x);
	prev->next = newnode;
	newnode->next = pos;
	}
}
void SListRemoveElement(SLTNode** pphead, SListDataType x)
{
	SLTNode* cur = *pphead;
	SLTNode* prev = NULL;
	while (cur)
	{
		//找到了分两种情况
	    if (cur->data == x)
		{
//          第一种是在头结点
			if (cur == *pphead)
			{
				*pphead = cur->next;
				free(cur);
				cur = *pphead;
			}
//          第二种是在中间节点
			else
			{
				prev->next = cur->next;
				free(cur);
				cur = prev->next;
			}
		}
		else
		{
			prev = cur;
			cur = cur->next;
		}
	}
}

void SListInsertAfter(SLTNode** pphead, SLTNode* pos,SListDataType x)
{
	SLTNode*newnode=BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值