C实现单链表

目录

1.单链表的概念

2.单链表的实现

2.1头文件

2.2test.c文件

2.3单链表增删查改的实现

3.总结   


1.单链表的概念

那么什么是链表呢?其实链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。简单来说就是自己定义了一个结构体构体,结构体里面有多个对象,其中常见的包括存储数据对象和结构体类型地址,(其实就是套娃,只要下一个结构体地址开辟完成后,让上一个在结构体对象里的结构体地址与刚开辟好的新节点地址相同就能实现单链表的连接)。

    无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
    带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。下面我们来实现单链表。

2.单链表的实现

2.1头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;

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



SlistPushBack(Slist**ps, DataType x);
Slistprint(Slist*ps);
SlistDestroy(Slist**ps);
SlistPopBack(Slist**ps);
SlistPushFront(Slist** ps, DataType x);
SlistPopFront(Slist**ps);
Slist*SlistFind(Slist*ps, DataType x);
SlistInsert(Slist*pos, DataType x);

2.2test.c文件

void SlistTest2()
{
	Slist* phead = NULL;
	SlistPushBack(&phead, 1);
	SlistPushBack(&phead, 2);
	SlistPushBack(&phead, 3);

	Slistprint(phead);

	SlistPopBack(&phead);
	SlistPopBack(&phead);
	SlistPopBack(&phead);

	Slistprint(phead);

	SlistPushFront(&phead,11);
	SlistPushFront(&phead, 12);
	SlistPushFront(&phead, 13);

	Slistprint(phead);

	SlistPopFront(&phead);
	SlistPopFront(&phead);

	Slistprint(phead);

	Slist* pos = SlistFind(phead, 11);
	//在pos位置后面加入
	SlistInsert(pos, 100);
	Slistprint(phead);

	SlistDestroy(&phead);
}

int main()
{
	//1.顺序表测试
	//SlistTest1();
	//2.单链表测试
	SlistTest2();

	return 0;
}

2.3单链表增删查改的实现

比较简单,不详细讨论,只想自己复习一下。

#include"Slist.h"

Slist* BuyNode(DataType x)
{
	Slist* tmp = (Slist*)malloc(sizeof(Slist));
	if (tmp == NULL)
	{
		printf("空间开辟失败\n");
		exit(-1);
	}
	else {
		tmp->data = x;
		tmp->next = NULL;
	}
	return tmp;
}

SlistPushBack(Slist** ps, DataType x)
{
	assert(ps);
	Slist* newnode = BuyNode(x);
	Slist* findtail = *ps;
	if (*ps == NULL)
	{
		*ps = newnode;
	}
	else {
		while (findtail->next!=NULL)
		{
			findtail = findtail->next;
		}
	   findtail->next = newnode;
	}
}


Slistprint(Slist* ps)
{
	Slist* cur = ps;
	while (cur)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

SlistDestroy(Slist** ps)
{
	assert(ps);
	Slist* cur = *ps;
	while (cur)
	{
		Slist* next =cur->next;
		free(cur);
		cur = next;
	}
	*ps = NULL;
}

SlistPopBack(Slist** ps)
{
	assert(ps);
	
	if (*ps == NULL)
	{
		return 1;
	}
	else if((*ps)->next==NULL)
	{
		free(*ps);
		*ps = NULL;
	}
	else
	{
		Slist* tail = *ps;
		Slist* prve = NULL;
		while (tail->next!=NULL)
		{
			prve = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		prve->next = NULL;

	}
	Slist* cur = *ps;

}

SlistPushFront(Slist** ps, DataType x)
{
	assert(ps);
	if (*ps == NULL)
	{
		Slist* newnode = BuyNode(x);
		*ps = newnode;
	}
	else {
		Slist* newnode = BuyNode(x);
		newnode->next = *ps;
		*ps = newnode;
	}

}

SlistPopFront(Slist** ps)
{
	assert(ps);
	if (*ps == NULL)
	{
		return 0;
	}
	else if ((*ps)->next == NULL)
	{
		free(*ps);
			* ps = NULL;
	}
	else {
		Slist* next = (*ps)->next;
		free(*ps);
		*ps = next;
	}
}

Slist* SlistFind(Slist* ps, DataType x)
{
	Slist* cur = ps;
	while (cur)
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	return NULL;
}

SlistInsert( Slist* pos, DataType x)
{
   assert(pos);
	Slist* newnode = BuyNode(x);
	Slist* next = pos->next;
	pos->next = newnode;
	newnode->next = next;
}


3.总结   

单链表结构,适合头插头删。尾部或者中间某个位置插入删除不适合。
如果要使用链表单独存储数据,带头双向链表更合适,单链表的使用一般都结合图的邻接表,哈希桶这些。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值