C语言初阶数据结构(二)单链表(详细图解,一看就懂)

目录

一、功能实现(图解)以及效果展示

1.1.定义结构体变量

1.2尾插数据

1.3头插数据

1.4尾删数据

1.5头删数据

1.6查找数据

1.7随机插入数据

1.8随机删除数据

1.9打印数据

二、完整代码


菜单展示

一、功能实现+图解+效果展示

1.首先定义一个结构体变量,成员变量包括数据域和指针域

struct SListNode
{    
    SLTDataType data;//数据域
    struct SListNode* next;//指针域
};

2.尾插数据

首先创建一个新结点,存放要插入的数据

1)如果无头结点,直接将该新结点作为头结点。

2)如果有头结点就需要遍历找为尾结点,然后将新结点插入到尾结点后即可

void SListPushBack(SLTNode* *pphead, SLTDataType x)
{
    SLTNode* newnode = BuySListNode(x);
    if (*pphead == NULL)
    {
        *pphead = newnode;
    }
    //找尾指针
    else
    {
        SLTNode* tail = *pphead;
        while (tail->next != NULL)
        {
            tail = tail->next;
        }
        //尾结点,链接新结点
        tail->next = newnode;
    }
}

效果展示

3.头插数据:将新创建的结点作为头结点

void SListPushFront(SLTNode** pphead, SLTDataType x)
{
    SLTNode* newnode = BuySListNode(x);
    newnode->next = *pphead;
    *pphead = newnode;
}

 效果展示

4.尾删数据:

1)如果链表为空,结束操作

2)如果只有头结点,直接删除头结点即可

3) 节点数大于1时,直接遍历找到最后一个结点然后删除即可,最后将倒数第二个结点的指针域为空即可。

void SListPopBack(SLTNode** pphead)
{
    //1.如果为空  2.如果只有一个结点  3.正常
    if (*pphead == NULL)
    {
        perror("");
        return;
    }
    else if((*pphead)->next==NULL)
    {
        free(*pphead);
        *pphead = NULL;
    }
    else
    {
        SLTNode* pre = NULL;
        SLTNode* tail = *pphead;
        while (tail->next != NULL)
        {
            pre = tail;
            tail = tail->next;
        }
        free(tail);
        pre->next = NULL;
    }
}

效果展示

5.头删数据:

1)如果链表为空,结束操作。

2)如果只有头结点,直接删除头结点即可。

3)结点数大于1时,创建一个新指针str ,使str指向头结点的下一个结点,然后将头结点释放,此时再将str的地址赋给*pphead,使其成为头结点

void SListPopFront(SLTNode** pphead)
{
    //1.空   2.正常
    if (*pphead == NULL)
    {
        perror("");
        return;
    }
    else
    {
        SLTNode* str = (*pphead)->next;
        (*pphead)->next = str;
        free(*pphead);
        *pphead = str;
    }
}

效果展示

6.查找数据:(效果展示与7和8搭配使用)

从头结点开始遍历链表,找到就返回结点地址,没找到就返回NULL

SLTNode* SListFind(SLTNode** pphead, SLTDataType x)
{
    SLTNode* cur = *pphead;
    while (cur != NULL)
    {
        if (cur->data == x)
        {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}

7.随机插入数据:

1.如果想插入元素的位置刚好是头结点,直接调用头插数据即可

 2..如果想插入元素的位置不是头结点,设置一个指针pre去查询想插入数据的位置,当pre->next指向的位置刚好是pos的位置时,将创建好的结点的插入其中即可。

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
    if (pos == *pphead)
    {
        SListPushFront(pphead, x);
    }
    else
    {
        SLTNode* newnode = BuySListNode(x);
        newnode->next = pos;
        SLTNode* pre = *pphead;
        while (pre->next != pos)
        {
            pre = pre->next;
        }
        pre->next = newnode;
    }
}

效果展示

8.随机删除数据

1.如果删除位置刚好是头结点,直接调用头删函数即可

2.如果删除位置不是头结点,设置一个指针pre去查询想删除的位置,当pre->next指向的位置刚好是pos的位置时, 让pre指针域指向pos的后一个位置,然后释放pos即可。

void SListErase(SLTNode** pphead, SLTNode* pos)
{
    if (pos == *pphead)
    {
        SListPopFront(pphead);
    }
    {
        SLTNode* pre = *pphead;
        while (pre->next != pos)
        {
            pre = pre->next;
        }
        pre->next = pos->next;
        free(pos);
        pos = NULL;
    }
}

效果实现

9.打印单链表:

遍历打印即可

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

二、完整代码

头文件SList.h(函数声明)

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

//链表
struct SListNode
{    
	SLTDataType data;//数据域
	struct SListNode* next;//指针域
};
typedef struct SListNode SLTNode;
//打印功能   不会改变链表的头指针,传一级指针
void SListPrint(SLTNode* phead);
//尾插  头插  尾删  头删  随机插入    随机删除  会改变链表的头指针,传二级指针
void SListPushBack(SLTNode** pphead, SLTDataType x);
void SListPushFront(SLTNode** pphead, SLTDataType x);
void SListPopBack(SLTNode** pphead);
void SListPopFront(SLTNode** pphead);
SLTNode* SListFind(SLTNode** pphead, SLTDataType x);
//在pos的前面插入x
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//删除pos位置的值
void SListErase(SLTNode** pphead, SLTNode* pos);

源文件SList.c(函数功能实现)

#include"SList.h"
//打印
void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

//创建新结点
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//尾插
void SListPushBack(SLTNode* *pphead, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	//找尾指针
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		//尾结点,链接新结点
		tail->next = newnode;
	}
}

//头插
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

//尾删
void SListPopBack(SLTNode** pphead)
{
	//1.如果为空  2.如果只有一个结点  3.正常
	if (*pphead == NULL)
	{
		perror("");
		return;
	}
	else if((*pphead)->next==NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* pre = NULL;
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			pre = tail;
			tail = tail->next;
		}
		free(tail);
		pre->next = NULL;
	}
}

//头删
void SListPopFront(SLTNode** pphead)
{
	//1.空   2.正常
	if (*pphead == NULL)
	{
		perror("");
		return;
	}
	else
	{
		SLTNode* str = (*pphead)->next;
		(*pphead)->next = str;
		free(*pphead);
		*pphead = str;
	}
}

//查找数据
SLTNode* SListFind(SLTNode** pphead, SLTDataType x)
{
	SLTNode* cur = *pphead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//随机插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	if (pos == *pphead)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SLTNode* newnode = BuySListNode(x);
		newnode->next = pos;
		SLTNode* pre = *pphead;
		while (pre->next != pos)
		{
			pre = pre->next;
		}
		pre->next = newnode;
	}
}

//随机删除
void SListErase(SLTNode** pphead, SLTNode* pos)
{
	if (pos == *pphead)
	{
		SListPopFront(pphead);
	}
	{
		SLTNode* pre = *pphead;
		while (pre->next != pos)
		{
			pre = pre->next;
		}
		pre->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

源文件text.c(功能测试)

#include"SList.h"
void menu()
{
	printf("*************************************\n");
	printf("**1.尾插数据             2.头插数据 \n");
	printf("**3.删除尾数据           4.删除首数据\n");
	printf("**5.随机插入数据         6.随机删除数据\n");
	printf("**7.打印数据              0.退出程序**\n");
	printf("*************************************\n");
	printf("请输入你的选择:>\n");
}
void Text()
{
	int input = 0;
	SLTDataType x = 0;
	SLTNode* plist = NULL;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入你想插入的数据,以-1结束\n");
			do
			{
				scanf("%d", &x);
				if (x != -1)
				{
					SListPushBack(&plist, x);
				}
			} while (x != -1);
			break;
		case 2:
			printf("请输入你想插入的数据,以-1结束\n");
			do
			{
				scanf("%d", &x);
				if (x != -1)
				{
					SListPushFront(&plist, x);
				}
			} while (x != -1);
			break;
		case 3:
			SListPopBack(&plist);
			printf("删除成功!\n");
			break;
		case 4:
			SListPopFront(&plist);
			printf("删除成功!\n");
			break;
		case 5:
			printf("请先输入你要插入的位置的当前数据:\n");
			scanf("%d", &x);
			SLTNode* pos = SListFind(&plist, x);
			if (pos == NULL)
			{
				printf("该数据不存在,请重新选择随机插入选项进行操作!\n");
			}
			else
			{
				printf("该数据存在,请输入您要插入的数据:\n");
				scanf("%d", &x);
				SListInsert(&plist, pos, x);
				printf("插入成功!\n");
			}
			break;
		case 6:
			printf("请先输入你要删除的位置的当前数据:\n");
			scanf("%d", &x);
			SLTNode* pos1 = SListFind(&plist, x);
			if (pos1 == NULL)
			{
				printf("该数据不存在,请重新选择随机删除选项进行操作!\n");
			}
			else
			{
				SListErase(&plist, pos1);
				printf("删除成功!\n");
			}
			break;
		case 7:
			SListPrint(plist);
			break;
		case 0:
			printf("退出程序!\n");
			break;
		default:
			printf("输入的数字有误,请重新选择\n");
			break;
		}
	} while (input);
}
int main()
{
	Text();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值