目录
菜单展示
一、功能实现+图解+效果展示
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;
}