c语言链表的实现

 概念:链表是一个物理上非连续存储,非顺序的数据结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的

 在链表中我们最常用的还是两种数据结构:
1.无头单向非循环链表:结构简单,一般来说不会单独用来存放数据。实际中更多是作为其他数据结构的子结构,如哈希桶,图的邻接图等等。另外这种数据结构在笔试面试中出现的很多。

2.带头双向循环链表:结构最复杂,一般用在单独的存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然复杂,但是使用代码实现后会发现结构带来很多优势,实现反而简单,下篇我们实现代码就知道了。

无头单向非循环链表的实现:我们也以类似工程的方式进行实现:

SList.h:函数声明
 

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLNDataTypa;
//定义一个结构体,里面包含一个结构体指针
typedef struct SListNode
{
	SLNDataTypa val;
	struct SListNode* next;
}SLNode;

//链表打印
void SLTPrint(SLNode*phead);

//链表尾插  //对形参的改变需要传地址
void SLTPushBack(SLNode** pphead, SLNDataTypa x);

//链表头插
void SLTPushFront(SLNode**pphead, SLNDataTypa x);

//链表尾删
void SLTPopBack(SLNode** pphead);

//链表头删
void SLTPopFront(SLNode** pphead);

//链表查找
SLNode* SLTFind(SLNode* plist, SLNDataTypa x);

//在pos位置之前插入
void SLTInsert(SLNode**pphead, SLNode* pos,SLNDataTypa x);

SList.c 函数定义
 

#include"SList.h"

//链表打印
void SLTPrint(SLNode*phead)
{
	SLNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL\n");
}

//创建节点 
SLNode* CreateNode(SLNDataTypa x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	if (newnode == NULL)
	{
		perror("mallo fail");
		exit(-1);
	}
	newnode->val = x;
	newnode->next = NULL;
	return newnode;
}


//链表尾插
void SLTPushBack(SLNode** pphead, SLNDataTypa x)
{
	//找尾
	SLNode* newnode = CreateNode(x);
	if (*pphead == NULL)
	{
		*pphead =newnode;
		//改变结构体外面的指针node*
		//需要用二级指针node**
	}
	else
	{

		//找尾
		SLNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}

}

//链表头插
void SLTPushFront(SLNode**pphead, SLNDataTypa x)
{
	SLNode* newnode = CreateNode(x);
		newnode->next = *pphead;
		*pphead = newnode;
}

//链表尾删
void SLTPopBack(SLNode** pphead)
{
	//空
	assert(*pphead);
	//一个节点,多个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLNode* tail = *pphead;
		SLNode* prev = NULL;//*pphead ; //=*pphead的话,一个指针后面free掉tail的时候,变为野指针了
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL; //好习惯,出作用域访问不到
		prev->next = NULL;
	}
}

//不需要prev
//while (tail->next->next != NULL)
//{
//	tail = tail->next;
//}
//free(tail->next);
//tail->next = NULL;

//链表头删
void SLTPopFront(SLNode** pphead)
{
	assert(*pphead);
	//一个节点,即以上都能处理
	SLNode* tmp = (*pphead)->next;
	free(*pphead);
	*pphead = tmp;
}

//链表查找
SLNode* SLTFind(SLNode* pphead, SLNDataTypa x)
{
	assert(pphead);
	SLNode* cur = pphead;
	while (cur)
	{
		if (cur->val == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
		
	}
	return NULL;
}

//在pos位置之前插入
void SLTInsert(SLNode**pphead, SLNode* pos, SLNDataTypa x)
{
	assert(pphead);
	//assert(*pphead);
	//两个都是空,要么都不是空
	assert((!pos && !(*pphead)) || (pos && *pphead));
	if (*pphead == pos)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		SLNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLNode* newnode = CreateNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}

}

test.c:
 

#include"SList.h"

void test1()
{
	//尾插
	SLNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPrint(plist);

	//头插
	SLTPushFront(&plist, 2);
	SLTPrint(plist);

	//尾删

	SLTPopBack(&plist);
	SLTPrint(plist);
	SLTPopBack(&plist);
	SLTPrint(plist);
   
    
	

	//头删
	SLTPopFront(&plist);
	SLTPrint(plist);
	
	//查找
	SLNode*pos=SLTFind(plist,2);

	//插入
	SLTInsert(&plist, pos,20);
	SLTPrint(plist);


	pos = SLTFind(plist, 1);
	SLTInsert(&plist, pos, 40);
	SLTPrint(plist);


	
}
int main()
{
	test1();
		
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值