用C程序实现一个单链表

创建malloc指针的节点

SLTNode* BuySLTNode(SLTDataType x);

SLTNode* BuySLTNode(SLTDataType x)//创建malloc指针的节点
{
	SLTNode* newnode = (SLTNode * )malloc(sizeof(SLTNode));
	if ((newnode == NULL))
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

打印链表

void SListPrint(SLTNode* phead);

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;//phead赋值给结构体cur的指针,指向第一个节点
	while(cur!=NULL)//cur不等于空就继续
	{
		printf("%d->",cur->data);
		cur = cur->next;//cur移动到下一个节点
	}
	printf("NULL\n");//打印空
}

链表的销毁

void SListDestory(SLTNode** pphead);

void SListDestory(SLTNode** pphead)//链表是需要销毁的
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)//指针直接去做逻辑判断
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

头插

void SListPushFront(SLTNode** pphead, SLTDataType x);

void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = *pphead;
	*pphead = newnode;//指向同一个位置
}

尾插

void SListPushBack(SLTNode** pphead, SLTDataType x);

void SListPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	//1.空
	//2.非空
	if (*pphead == NULL)
	{
		*pphead = newnode;//存的是plist的地址
	}
	//链表不为空,尾插,要改变的是结构体SListNode的成员
	//tail就是结构体的指针
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next!=NULL)
		{
			tail = tail->next;
		}
		tail->next= newnode;
	}
}

尾删

void SListPushBack(SLTNode** pphead, SLTDataType x);

void SListPopBack(SLTNode** pphead)
{
	assert(pphead);
	//1.一个节点
	//.多个节点
	// 温柔的检查
	 if(*pphead==NULL)
	 {
	 return;
	 }
	//暴力检查
	//assert(*pphead != NULL);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//方法一
		//assert(pphead);
		//SLTNode* prev = NULL;
		//SLTNode* tail = *pphead;
		//while (tail->next!= NULL)
		//{
		//	prev = tail;
		//	tail = tail->next;
		//}
		//prev->next = NULL;
		//free(tail);
		//tail = NULL;
	//方法二
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

头删

void SListPopFront(SLTNode** pphead);

void SListPopFront(SLTNode** pphead)
{
	assert(pphead);//一级指针有时候检查有时候不检查,看场景,二级都要检查
	//温柔的检查
	if (*pphead == NULL)
	{
		return ;
	}
	//暴力检查
	//assert(*pphead!= NULL);
	SLTNode* del = *pphead;
	//同一priority(优先级)加个括号告诉编译器
	*pphead =(*pphead)->next;
	free(del);
	del = NULL;
}
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

这是我SList.h里的代码:

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLTDataType;//定义节点
typedef struct SLisNode
{
	SLTDataType data;
	struct SLisNode* next;//结构体指针指向下一个结构的指针
} SLTNode;
SLTNode* BuySLTNode(SLTDataType x);//创建malloc指针的节点
void SListPrint(SLTNode* phead);//打印链表
void SListDestory(SLTNode** pphead);//链表是需要销毁的
void SListPushFront(SLTNode** pphead, SLTDataType x);//头插
void SListPushBack(SLTNode** pphead, SLTDataType x);//尾插
void SListPushBack(SLTNode** pphead, SLTDataType x);//尾删
void SListPopFront(SLTNode** pphead);//头删

SLTNode* SListFind(SLTNode* phead,SLTDataType x);//查找链表
//单链表在pos之前插入
void SListInsert(SLTNode** pphead, SLTNode*pos, SLTDataType x);
//单链表在pos后面插入
void SListInsertAfter(SLTNode* pos,SLTDataType x);
//删除pos位置
//void SListErase(SLTNode** pphead,SLTNode* pos);
//删除pos后面位置
//void SListEraseAfter( SLTNode* pos);

 

这是我SList.c里的代码:

#include"SList.h"
void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;//phead赋值给结构体cur的指针,指向第一个节点
	while(cur!=NULL)//cur不等于空就继续
	{
		printf("%d->",cur->data);
		cur = cur->next;//cur移动到下一个节点
	}
	printf("NULL\n");//打印空
}
SLTNode* BuySLTNode(SLTDataType x)//创建malloc指针的节点
{
	SLTNode* newnode = (SLTNode * )malloc(sizeof(SLTNode));
	if ((newnode == NULL))
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void SListDestory(SLTNode** pphead)//链表是需要销毁的
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)//指针直接去做逻辑判断
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = *pphead;
	*pphead = newnode;//指向同一个位置
}
void SListPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuySLTNode(x);
	//1.空
	//2.非空
	if (*pphead == NULL)
	{
		*pphead = newnode;//存的是plist的地址
	}
	//链表不为空,尾插,要改变的是结构体SListNode的成员
	//tail就是结构体的指针
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next!=NULL)
		{
			tail = tail->next;
		}
		tail->next= newnode;
	}
}
void SListPopBack(SLTNode** pphead)
{
	assert(pphead);
	//1.一个节点
	//.多个节点
	// 温柔的检查
	 if(*pphead==NULL)
	 {
	 return;
	 }
	//暴力检查
	//assert(*pphead != NULL);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//方法一
		//assert(pphead);
		//SLTNode* prev = NULL;
		//SLTNode* tail = *pphead;
		//while (tail->next!= NULL)
		//{
		//	prev = tail;
		//	tail = tail->next;
		//}
		//prev->next = NULL;
		//free(tail);
		//tail = NULL;
	//方法二
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}
void SListPopFront(SLTNode** pphead)
{
	assert(pphead);//一级指针有时候检查有时候不检查,看场景,二级都要检查
	//温柔的检查
	if (*pphead == NULL)
	{
		return ;
	}
	//暴力检查
	//assert(*pphead!= NULL);
	SLTNode* del = *pphead;
	//同一priority(优先级)加个括号告诉编译器
	*pphead =(*pphead)->next;
	free(del);
	del = NULL;
}
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//在pos之前插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SListPushFront(pphead,x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
			assert(prev);//找不到不要尾插
		}
		SLTNode* newnode = BuySLTNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}
//在pos后面插入
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySLTNode(x);
	//后插注意顺序
	newnode->next = pos->next;
	pos->next = newnode;
}


这是我Test.c里的代码:

#include"SList.h"
void TestSList1()
{
	SLTNode* plist = NULL;
	SListPushFront(&plist, 1);
	SListPushFront(&plist, 2);
	SListPushFront(&plist, 3);
	SListPushFront(&plist, 4);

	SListPrint(plist);

	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
	SListPopFront(&plist);
	SListPrint(plist);
}
void TestSList2()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);
	SListPrint(plist);

	SListPopBack(&plist);
	SListPrint(plist);
	SListPopBack(&plist);
	SListPrint(plist);
	SListPopBack(&plist);
	SListPrint(plist);
	SListPopBack(&plist);
	SListPrint(plist);

	SListPopBack(&plist);
	SListPrint(plist);

	SListDestory(&plist);
}
void TestSList3()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);
	SListPrint(plist);

	SLTNode* pos = SListFind(plist, 3);
	if (pos)
	{
		pos->data *= 10;

		printf("找到了\n");
	}
	else
	{
		printf("没有找到\n");
	}
	SListPrint(plist);
    pos = SListFind(plist,1);
	if (pos)
	{
		SListInsert(&plist, pos, 10);//1的前面插入10
	}
	SListPrint(plist);
	SListDestory(&plist);
}
//改变int*要传二级指针
//void swapi(int* px, int* py)
//{
//	int tmp = *px;
//	*px = *py;
//	*py = tmp;
//}
//void swapptr(int** ppx, int** ppy)
//{
//	int* tmp = *ppx;
//	*ppx = *ppy;
//	*ppy = tmp;
//}
int main()
{
	//int x = 0;
	//int y = 1;
	//swapi(&x, &y);
	//int* p1 = &x, * p2 = &y;
	//swapptr(&p1, &p2);
	//TestSList1();
	//TestSList2();
	TestSList3();
	return 0;
}

我们现在是想在第三个位置插入数字30,在1的前面插入10,检查一下运行结果:
在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值