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;

}

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

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

相关推荐
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
阿史大杯茶1 小时前
AtCoder Beginner Contest 381(ABCDEF 题)视频讲解
数据结构·c++·算法
Chris _data2 小时前
二叉树oj题解析
java·数据结构
Lenyiin3 小时前
02.06、回文链表
数据结构·leetcode·链表
爪哇学长3 小时前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
爱摸鱼的孔乙己3 小时前
【数据结构】链表(leetcode)
c语言·数据结构·c++·链表·csdn
烦躁的大鼻嘎3 小时前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
C++忠实粉丝4 小时前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
daiyang123...5 小时前
测试岗位应该学什么
数据结构
kitesxian5 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode