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;

}

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

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

相关推荐
XuanRanDev3 小时前
【数据结构】树的基本:结点、度、高度与计算
数据结构
苦 涩7 小时前
考研408笔记之数据结构(七)——排序
数据结构
Victoria.a8 小时前
顺序表和链表(详解)
数据结构·链表
笔耕不辍cj9 小时前
两两交换链表中的节点
数据结构·windows·链表
csj5010 小时前
数据结构基础之《(16)—链表题目》
数据结构
謓泽10 小时前
【数据结构】二分查找
数据结构·算法
攻城狮7号11 小时前
【10.2】队列-设计循环队列
数据结构·c++·算法
写代码超菜的12 小时前
数据结构(四) B树/跳表
数据结构
小小志爱学习12 小时前
提升 Go 开发效率的利器:calc_util 工具库
数据结构·算法·golang
egoist202312 小时前
数据结构之堆排序
c语言·开发语言·数据结构·算法·学习方法·堆排序·复杂度