(注意事项都已经在代码中标注)
1.链表相关函数的头文件
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
typedef int datatype;
typedef struct slistnode {
datatype data;
struct slistnode* node;
}slnode;
void menu();
void slprint(slnode* slist1);//展示
void slpush_back(slnode** slist1, datatype x);//尾增
void slpush_front(slnode** slist1, datatype x);//头增
slnode* sl_find(slnode* slist1, datatype x);//查找
void slpop_back(slnode** slist1);//尾删
void slpop_front(slnode** slist1);//头删
void slpush_onin(slnode** slist1, slnode* pos, datatype x);//在指定位置前面增,这里使用的是找前驱,但是实际上可以改该位置的数据,再生成一个新的结点使用该位置的data连接上去,就不需要找前驱
void slpop_onin(slnode** slist1, slnode* pos);//删除指定位置的数据
2.具体实现的函数
#include "slist.h"
void menu() {
printf("******************************\n");
printf("***1.头插 2.尾插***\n");
printf("***3.头删 4.尾删***\n");
printf("***5.在指定数前面增加一个数***\n");
printf("***6.删除指定第一个数 ***\n");
printf("***0.exit ***\n");
printf("******************************\n");
}
void slprint(slnode* slist1) {
if (slist1 == NULL) {
printf("该链表暂时并没有任何的结点,无法打印\n");
}
else{
printf("开始打印该链表中的内容:");
while (slist1 != NULL) {
printf("%d->", slist1->data);
slist1 = slist1->node;
}
printf("NULL");
printf("\n打印结束\n");
printf("-----------------------------\n");
}
}
slnode* buynewnode(datatype x) {
slnode* newnode = (slnode*)malloc(sizeof(slnode));
if (newnode != NULL) {
newnode->data = x;
newnode->node = NULL;
return newnode;
}
else {
printf("buynewnode err:%s\n", strerror(errno));
return NULL;
}
}
void slpush_back(slnode** slist1, datatype x) {
slnode* newnode = buynewnode(x);
if (*slist1 == NULL) {
*slist1 = newnode;//这里就是尾删为什么使用二级指针的原因
}
else {
slnode* slist_tmp = *slist1;
while (slist_tmp->node != NULL) {
slist_tmp = slist_tmp->node;
}
slist_tmp->node =newnode;
}
}
void slpush_front(slnode** slist1, datatype x) {
slnode* newnode = buynewnode(x);
if (*slist1 == NULL) {
*slist1 = newnode;//这里就是头插为什么使用二级指针的原因
}
else {
newnode->node = *slist1;
*slist1 = newnode;
}
}
slnode* sl_find(slnode* slist1, datatype x) {
if (slist1 == NULL) {
printf("该链表暂时为空\n");
return NULL;
}
else{
while (slist1->data != x) {
slist1 = slist1->node;
}
return slist1;
}
}
void slpop_back(slnode** slist1) {
slnode* prev = *slist1;
slnode* slist1_tmp = *slist1;
if (slist1_tmp == NULL) {
return;
}
else if(slist1_tmp->node==NULL){
free(*slist1);
*slist1 = NULL;//这里的分类讨论要注意,为什么在尾删也需要二级指针,因为在这里需要直接让他指向空;头指针发生了变化
}
else {
while (slist1_tmp->node != NULL) {
prev = slist1_tmp;
slist1_tmp = slist1_tmp->node;
}
prev->node = NULL;
free(slist1_tmp);//这里没有分类讨论的话,前驱跟找尾部的指针会指向同一个,会有特殊的地方
}
}
void slpop_front(slnode** slist1) {
slnode* flag_slist1 = *slist1;
if (*slist1 == NULL) {
return;
}
else {
(*slist1) = (*slist1)->node;//头删很显然就是需要使用二级指针的
free(flag_slist1);
flag_slist1 = NULL;
}
}
void slpush_onin(slnode** slist1, slnode *pos,datatype x) {//找到的该数后在前面增加一个数
if (*slist1==pos) {
slpush_front(slist1, x);
}
else{
slnode* slist1_tmp = *slist1;
while (slist1_tmp->node != pos) {
slist1_tmp = slist1_tmp->node;
}
slnode* newnode = buynewnode(x);
slist1_tmp->node = newnode;
newnode->node = pos;
}
}
void slpop_onin(slnode** slist1, slnode* pos) {//删除指定位置的的数,上下这两个都是在一个的时候会有特殊情况,就是相当于头删和头增
if (*slist1 == pos) {
slpop_front(slist1);
}
else {
slnode* slist1_tmp = *slist1;
while (slist1_tmp->node != pos) {
slist1_tmp = slist1_tmp->node;
}
slist1_tmp->node = pos->node;
free(pos);
}
}
3.主函数
#include "slist.h"
int main() {
int input = 0;
slnode* slist1 = NULL;
do {
menu();
printf("请输入你想要进行的操作数\n");
scanf("%d", &input);
switch (input) {
case 1:
printf("请输入你要头插的数\n");
int n = 0;
scanf("%d", &n);
slpush_front(&slist1, n);
slprint(slist1);
break;
case 2:
printf("请输入你要尾插的数\n");
n = 0;
scanf("%d", &n);
slpush_back(&slist1, n);
slprint(slist1);
break;
case 3:
printf("正在进行头删\n");
slpop_front(&slist1);
slprint(slist1);
printf("头删结束\n");
break;
case 4:
printf("正在进行尾删\n");
slpop_back(&slist1);
slprint(slist1);
printf("尾删结束\n");
break;
case 5:
printf("正在进行指定数前加\n");
printf("请输入指定数\n");
int x = 0;
scanf("%d", &x);
slnode* pos = sl_find(slist1,x);
if (pos) {
printf("可以进行前加,正在进行前加\n");
printf("请输入你要加入的数\n");
scanf("%d", &n);
slpush_onin(&slist1, pos, n);
}
else
printf("没有找到指定的数\n");
slprint(slist1);
break;
case 6:
printf("正在进行指定数删除\n");
printf("请输入指定数\n");
x = 0;
scanf("%d", &x);
pos = sl_find(slist1, x);
if (pos) {
printf("正在进行删除\n");
slpop_onin(&slist1, pos);
}
else
printf("没有找到指定的数\n");
slprint(slist1);
break;
case 0:
printf("正在退出程序\n");
break;
default:
printf("您的输入存在错误\n");
}
} while (input);
return 0;
}
//注意事项,当在指定位置进行插入的时候,只有一个相当于头插,不能直接使用原来的方法,否则会报错
//同理删指定位置,就相当于头删