[数据结构]:单链表(无头+单向+非循环链表)增删查改功能的实现

1.什么是链表

链表:是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的
在这里插入图片描述
实际中链表的结构非常多样,有以下情况组合起来的8种链表结构
a.单向,双向
b.带头,不带头
c.循环,不循环

如上图所示就是一个单链表的逻辑结构

2.增删查改功能图解

a.尾插

在这里插入图片描述

b.头插

在这里插入图片描述

c.尾删

在这里插入图片描述

e.头删

在这里插入图片描述

f.在pos位置之后插入x

在这里插入图片描述

g.删除pos位置之后的值

在这里插入图片描述

3.单链表的实现

(1)SingleList.h 单链表各项功能的接口及函数的声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int SLTDataType;
typedef struct SListNode
{
    
    
	//数据
	int data;
	//指针指向下一个节点
	struct SListNode* next;
}SListNode;

//打印链表
void SListPrintf(SListNode* phead);
//动态申请一个节点
SListNode* BuySListNode(SLTDataType x);
//尾插
void SListPushBack(SListNode** pphead, SLTDataType x);
//头插
void SListPushFront(SListNode** pphead, SLTDataType x);
//尾删
void SListPopBack(SListNode** pphead);
//头删
void SListPopFront(SListNode** pphead);
//查找
SListNode* SListFind(SListNode* phead, SLTDataType x);
//在pos位置之后插入x
void SListInsertAfert(SListNode* pos, SLTDataType x);
//删除pos位置之后的值
void SListEraseAfert(SListNode* pos);

(2)SingleList.c 各个接口功能的实现

#include"SingleList.h"
//打印链表
void SListPrintf(SListNode* phead)
{
    
    
	SListNode* cur = phead;
	while (cur != NULL)
	{
    
    
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
//动态申请一个节点
SListNode* BuySListNode(SLTDataType x)
{
    
    
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL)
	{
    
    
		printf("malloc node fail!\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//尾插
void SListPushBack(SListNode** pphead, SLTDataType x)
{
    
    
	SListNode* newnode = BuySListNode(x);
	//phead为空直接把newnode给phead
	if (*pphead == NULL)
	{
    
    
		*pphead = newnode;
	}
	else
	{
    
    
		SListNode* tail = *pphead;
		while (tail->next != NULL)
		{
    
    
			tail = tail->next;
		}
		tail->next = newnode;
	}

}
//头插
void SListPushFront(SListNode** pphead, SLTDataType x)
{
    
    
	//开一个新的节点
	SListNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
    
    
		*pphead = newnode;
	}
	else
	{
    
    
		SListNode* cur = *pphead;
		*pphead = newnode;
		newnode->next = cur;
	}
}
//尾删
void SListPopBack(SListNode** pphead)
{
    
    
	//防止空链表再删
	if (*pphead == NULL)
	{
    
    
		return;
	}
	//链表只有一个节点,防止空指针
	else if ((*pphead)->next == NULL)
	{
    
    
		//free的是这段空间,指针还在
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
    
    
		SListNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
    
    
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}
//头删
void SListPopFront(SListNode** pphead)
{
    
    
	//防止空链表再删
	if (*pphead == NULL)
	{
    
    
		return;
	}
	//链表只有一个节点,防止空指针
	else if ((*pphead)->next == NULL)
	{
    
    
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
    
    
		//保存pphead下一个节点的位置
		SListNode* cur = (*pphead)->next;
		free(*pphead);
		*pphead = cur;
	}

}
//查找
SListNode* SListFind(SListNode* phead, SLTDataType x)
{
    
    
	SListNode* cur = phead;
	while (cur != NULL)
	{
    
    
		if (cur->data == x)
		{
    
    
			printf("找到%d了\n", x);
			return cur;
		}
		else
		{
    
    
			cur = cur->next;
		}
	}
	printf("没找到%d\n", x);
	return NULL;
}
//在pos位置之后插入x
void SListInsertAfert(SListNode* pos, SLTDataType x)
{
    
    
	//开一个新的节点
	SListNode* newnode = BuySListNode(x);
	SListNode* posnext = pos->next;
	pos->next = newnode;
	newnode->next = posnext;
}
//删除pos位置之后的值
void SListEraseAfert(SListNode* pos)
{
    
    
	if (pos->next == NULL)
	{
    
    
		return;
	}
	else
	{
    
    
		SListNode* posnextnext = pos->next->next;
		free(pos->next);
		pos->next = NULL;
		pos->next = posnextnext;
	}
}

(3)test.c 用于测试各项功能

#include"SingleList.h"

int main()
{
    
    
	SListNode* phead = NULL;//空链表
	//尾插
	printf("尾插测试:\n\n");
	SListPushBack(&phead, 0);
	SListPushBack(&phead, 1);
	SListPushBack(&phead, 2);
	SListPushBack(&phead, 3);
	SListPushBack(&phead, 4);
	SListPushBack(&phead, 5);
	SListPrintf(phead);
	printf("\n");
	//头插
	printf("头插测试:\n\n");
	SListPushFront(&phead, -1);
	SListPushFront(&phead, -2);
	SListPushFront(&phead, -3);
	SListPushFront(&phead, -4);
	SListPushFront(&phead, -5);
	SListPrintf(phead);
	printf("\n");
	//尾删
	printf("尾删测试:\n\n");
	SListPopBack(&phead);
	SListPrintf(phead);
	printf("\n");
	//头删
	printf("头删测试:\n\n");
	SListPopFront(&phead);
	SListPrintf(phead);
	printf("\n");
	//查找
	printf("查找测试:\n\n");
	SListFind(phead, 3);
	printf("\n");
	//在pos位置之后插入x
	printf("在pos位置后插入x测试:\n\n");
	SListNode* pos = SListFind(phead,3);//先查找到链表中3的位置,再在3的位置后面插入30
	SListInsertAfert(pos, 30);
	SListPrintf(phead);
	printf("\n");
	//删除pos位置之后的值
	printf("删除pos位置之后的值测试:\n\n");
	SListNode* pos1 = SListFind(phead, 3);
	SListEraseAfert(pos1);
	SListPrintf(phead);
	printf("\n");
	return 0;
}

(4)测试结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_50886514/article/details/113808910