自学内容网 自学内容网

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;

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


原文地址:https://blog.csdn.net/2301_81172092/article/details/142883671

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!