c语言链表实现

(注意事项都已经在代码中标注)

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;

}

//注意事项,当在指定位置进行插入的时候,只有一个相当于头插,不能直接使用原来的方法,否则会报错

//同理删指定位置,就相当于头删

相关推荐
shinelord明几秒前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
薄荷故人_25 分钟前
从零开始的C++之旅——红黑树及其实现
数据结构·c++
努力学习编程的伍大侠37 分钟前
基础排序算法
数据结构·c++·算法
XiaoLeisj1 小时前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Jackey_Song_Odd2 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
乐之者v2 小时前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A3 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
️南城丶北离4 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻4 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
菜鸡中的奋斗鸡→挣扎鸡12 小时前
滑动窗口 + 算法复习
数据结构·算法