zoukankan      html  css  js  c++  java
  • 顺序表的连接储存(用链表实现)

     


     

    由于数组组成的线性表在插入,删除等操作时,时间效率下降。所以引入了链表来解决顺序储存引发数据移动的问题

    本次线性表用链表来完成。

    实现了链表功能的初始化,替换,查找,插入,删除,遍历,逆转等基本操作较为简单。

     



    以下单独给出链表逆序过程。
    /*------------------------------------------
    函数名:invertlist
    描  述:反转链表数据
    入口参数:无
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo invertlist() {
        PNODE nowp, midp, lastp;
        if (empty()) {
            return underflow;
        }
        nowp = headp->next;
        midp = NULL;
        //一个循环的起始状态时nowp在最前面 midp在后一个 lastp 在最后
        while (nowp != NULL) {
            //lastp 指针在最后 随前两个指针的移动而移动
            // 在上上一个循环 节点的->next已经指向前一个节点 
            //需要借助midp指针进行移动
            lastp = midp;
            //在后一个节点跟上之后 前面两个节点分别向前移动一次
            //在上次循环 midp的指针域已经指向前一个前面的节点
            //需要借助最前面的nowp指针进行移动
            midp = nowp;
            nowp = nowp->next;
            //此时三个指针分别指向三个连续不同的节点
            //需要把中间节点的指针域指向前一个节点
            midp->next = lastp;
        }//在循环最后 nowp指向NULL midp指向最后一个节点
        headp->next = midp;
        return success;
    }

    下面是完整代码:

    #include<stdio.h>
    #include<malloc.h>
    #include<windows.h>                 //清屏和颜色设置需要
    #include<stdbool.h>
    #define len sizeof(struct node)     //结构体node长度,即要申请空间的长度
    #define MAXNUMOFBASE 5              //定义常量表达数组的最大容量
    enum returninfo {success,fail,overflow,underflow,range_error}; //定义返回信息清单
    int sourcedata[MAXNUMOFBASE] = { 11,22,33,55,66 };     //内部数据数组,节省每次建立时输入时间
    typedef struct node {
        int data;                                //数据域
        struct node* next;                        //指针域
    }NODE,*PNODE;                                //NODE:struct node PNODE: struct node*
    
    PNODE headp;                                //全局变量,定义了头指针
    int count;                                    //全局变量,定义了计数器,统计线程表长度
    
    //功能函数声明
    void clearscreen();                         //清屏
    void initList();                            //初始化链表,启动头指针 headp
    int length();                                //求链表长度
    void showMenu();                            //显示菜单
    bool empty();                                //判断链表是否为空
    int userchoice();                            //返回用户的选择
    enum returninfo create();                   //建立链表
    void clearlist();                            //清空链表
    enum returninfo traverse();                    //遍历链表
    enum returninfo invertlist();                //反转链表数据
    void function(int choose);                    //执行指定功能
    int getcount() { return count; };            //得到当前节点个数
    enum returninfo remove(int position);        //删除节点
    enum returninfo insert(int position, int item);  //插入节点
    enum returninfo retrieve(int position, int* item); //读取一个节点
    enum returninfo replace(int position, int item);   //修改一个节点
    
    /*------------------------------------------
    函数名:clearscreen
    描  述:清屏
    入口参数:无
    出口参数:无
    -------------------------------------------*/
    void clearscreen() {
        system("cls");
    }
    
    /*------------------------------------------
    函数名:initList
    描  述:初始化链表
    入口参数:无
    出口参数:无
    -------------------------------------------*/
    void initList() {
        headp = (PNODE)malloc(len);
        headp->next = NULL;
        count = 0;
    }
    
    /*------------------------------------------
    函数名:length
    描  述:返回链表长度
    入口参数:无
    出口参数:int 型
    -------------------------------------------*/
    int length() {
        return count;
    }
    
    /*------------------------------------------
    函数名:showMenu
    描  述:显示功能菜单
    入口参数:无
    出口参数:无
    -------------------------------------------*/
    void showMenu() {
            printf("顺序表基本功能菜单              
    ");
            printf("=====================         
    ");
            printf("1.初始化链表(自动录入数组的值) 
    ");
            printf("2.显示数据(遍历全部数据)      
    ");
            printf("3.修改节点(要提供位置和新值)  
    ");
            printf("4.插入节点(要提供位置和新值)  
    ");
            printf("5.删除节点(要提供位置)       
    ");
            printf("6.读取数据(要提供位置)       
    ");
            printf("7.求表长度                    
    ");
            printf("8.数据反转(全部数据逆序存储)  
    ");
            printf("9.结束程序                    
    ");
            printf("=====================        
    ");
    }
    
    /*------------------------------------------
    函数名:empty
    描  述:判断链表是否为空
    入口参数:无
    出口参数:bool 型
    -------------------------------------------*/
    bool empty() {
        if (headp->next == NULL) {
            return true;
        }
        else {
            return false;
        }
    }
    
    /*------------------------------------------
    函数名:usechoose
    描  述:返回用户选择
    入口参数:无
    出口参数:int 型
    -------------------------------------------*/
    int userchoice() {
        int menuchoice;
        printf("请输入您的选择:");
        scanf_s("%d", &menuchoice);
        return menuchoice;
    }
    
    /*------------------------------------------
    函数名:create
    描  述:建立链表
    入口参数:无
    出口参数:enum returninfo 型
    -------------------------------------------*/
    enum returninfo create() {
        PNODE searchp = headp, newnodep;
        int i;
        for (i = 0; i < MAXNUMOFBASE; i++) {
            newnodep = (PNODE)malloc(len);
            newnodep->data = sourcedata[i];
            searchp->next = newnodep;
            searchp = newnodep;
            searchp->next = NULL;                 
            count++;
        }
        return success;
    }
    
    /*------------------------------------------
    函数名:clearlist
    描  述:清空链表
    入口参数:无
    出口参数:无
    -------------------------------------------*/
    void clearlist() {
        PNODE searchp = headp->next, follow = headp;
        while (searchp->next != NULL) {
            follow = searchp;
            searchp = searchp->next;
            free(follow);
        }
        headp->next = NULL;
        count = 0;
    }
    
    /*------------------------------------------
    函数名:teaverse
    描  述:遍历链表
    入口参数:无
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo traverse() {
        PNODE searchp;
        if (empty()) {
            return underflow;
        }
        searchp = headp->next;
        while (searchp != NULL) {
            printf("%d ",searchp->data);
            searchp = searchp->next;
        }
        printf("
    ");
        return success;
    }
    
    /*------------------------------------------
    函数名:invertlist
    描  述:反转链表数据
    入口参数:无
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo invertlist() {
        PNODE nowp, midp, lastp;
        if (empty()) {
            return underflow;
        }
        nowp = headp->next;
        midp = NULL;
        //一个循环的起始状态时nowp在最前面 midp在后一个 lastp 在最后
        while (nowp != NULL) {
            //lastp 指针在最后 随前两个指针的移动而移动
            // 在上上一个循环 节点的->next已经指向前一个节点 
            //需要借助midp指针进行移动
            lastp = midp;
            //在后一个节点跟上之后 前面两个节点分别向前移动一次
            //在上次循环 midp的指针域已经指向前一个前面的节点
            //需要借助最前面的nowp指针进行移动
            midp = nowp;
            nowp = nowp->next;
            //此时三个指针分别指向三个连续不同的节点
            //需要把中间节点的指针域指向前一个节点
            midp->next = lastp;
        }//在循环最后 nowp指向NULL midp指向最后一个节点
        headp->next = midp;
        return success;
    }
    
    /*------------------------------------------
    函数名:function
    描  述:执行指定功能
    入口参数:功能选项
    出口参数:无
    -------------------------------------------*/
    void function(int choose) {
        int position = 0, item, returnvalue;
        switch (choose) {                   //根据用户的选择进行相应的操作
        case 1:
            initList();
            returnvalue = create();
            if (returnvalue != success) {
                printf("生成链表错误!");
            }
            else {
                printf("链表初始化成功!
    ");
            }
            break;
        case 2:
            returnvalue = traverse();
            if (returnvalue == underflow) {
                printf("链表为空!
    ");
            }
            if (returnvalue == success) {
                printf("遍历链表操作成功!
    ");
            }
            break;
        case 3:
            printf("请输入您需要更改的位置:");
            scanf_s("%d", &position);
            printf("请输入您需要更改的值:");
            scanf_s("%d", &item);
            returnvalue = replace(position, item);
            if (returnvalue == underflow) {
                printf("对不起,链表表为空
    ");
            }
            else if (returnvalue == range_error) {
                printf("对不起,修改的位置超出了范围!
    ");
            }
            else {
                printf("修改成功!
    ");
            }
            break;
        case 4:
            printf("请输入您打算插入数据的位置:");
            scanf_s("%d", &position);
            printf("请输入您需要插入的新数据");
            scanf_s("%d", &item);
            returnvalue = insert(position, item);
            if (returnvalue == range_error) {
                printf("对不起,修改的位置超出了范围!
    ");
            }
            else {
                printf("插入操作成功!
    ");
            }
            break;
        case 5:
            printf("请输入您需要删除数据的位置:");
            scanf_s("%d", &position);
            returnvalue = remove(position);
            if (returnvalue == underflow) {
                printf("对不起,链表已空!
    ");
            }
            else if (returnvalue == range_error) {
                printf("对不起,删除的位置超出了范围!
    ");
            }
            else {
                printf("删除操作成功!
    ");
            }
            break;
        case 6:
            printf("请输入您需要读取的数据的位置:");
            scanf_s("%d", &position);
            returnvalue = retrieve(position, &item);
            if (returnvalue == underflow) {
                printf("对不起,链表已空!
    ");
            }
            else if (returnvalue == range_error) {
                printf("对不起,读取的位置超出了范围!
    ");
            }
            else {
                printf("读取的数据为:%d
    读取操作成功
    ", item);
            }
            break;
        case 7:
            printf("链表的长度为:%d
    ", length());
            printf("求链表长度操作成功!
    ");
            break;
        case 8:
            returnvalue = invertlist();
            if (returnvalue == overflow) {
                printf("对不起,链表已空!
    ");
            }
            else {
                printf("链表所有元素反转操作成功!
    ");
            }
            break;
        case 9:
            exit(0);
        default:
            printf("对不起您输入的编号有错!请重新输入!!!
    ");
            break;
        }
    }
    
    /*------------------------------------------
    函数名:remove
    描  述:删除节点
    入口参数:位置
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo remove(int position) {
        int i;
        PNODE searchp = headp->next, followp = headp;
        if (empty()) {
            return underflow;
        }
        if (position <= 0 || position > count) {
            return range_error;
        }
        for (i = 1; i < position; i++) {
            followp = searchp;
            searchp = searchp->next;
        }
        followp->next = searchp->next;
        free(searchp);
        searchp = NULL;
        count--;
        return success;
    }
    
    /*------------------------------------------
    函数名:insert
    描  述:插入节点
    入口参数:位置 插入值
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo insert(int position, int item) {
        int i;
        PNODE searchp = headp;
        PNODE newnodep = (PNODE)malloc(sizeof(len));
        if (position <= 0 || position > count + 1) {
            return range_error;
        }
    
        newnodep->data = item;
        for (i = 1; i < position; i++) {
            searchp = searchp->next;
        }
        newnodep->next = searchp->next;
        searchp->next = newnodep;
        count++;
        return success;
    }
    
    /*------------------------------------------
    函数名:retrieve
    描  述:得到指定节点的值
    入口参数:位置 存放数据的地址
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo retrieve(int position, int* item) {
        PNODE searchp = headp->next;
        int i;
        if (empty()) {
            return underflow;
        }
        if (position <= 0 || position >= count + 1) {
            return range_error;
        }
        for (i = 1; i < position; i++) {
            searchp = searchp->next;
        }
        *item = searchp->data;
        return success;
    }
    
    /*------------------------------------------
    函数名:replace
    描  述:替换指定节点的值
    入口参数:位置 替换的值
    出口参数:enum returninfo 型判断返回是否成功
    -------------------------------------------*/
    enum returninfo replace(int position, int item) {
        int i;
        PNODE searchp = headp->next;
        if (empty()) {
            return underflow;
        }
        if (position <= 0 || position >= count + 1) {
            return range_error;
        }
        for (i = 1; i < position; i++) {
            searchp = searchp->next;
        }
        searchp->data = item;
        return success;
    }
    
    int main(void) {
        SetConsoleTitle("顺序表实现线性表的基本功能(C语言版)");
        int menuchoice;                   //定义变量,菜单选单选的选择
    
        system("color f0");               //修改屏幕背景颜色和字体颜色
        clearscreen();                    //清屏
    
        while (true) {                   //永真循环
            showMenu();                  //显示菜单
            menuchoice = userchoice();   //获取用户的选择
            function(menuchoice);        //处理用户的选择
            system("pause");             //暂停
            clearscreen();               //清屏
        }
    
        return 0;
    }

     如有错误欢迎指正!!

     

  • 相关阅读:
    最全Linux应急响应技巧
    2016年总结
    idapython实现动态函数调用批量注释
    CVE-2015-7645 analyze and exploit
    CVE-2010-3654分析及利用
    apt28组织新的flash漏洞利用包dealerschoice分析
    Spartan Exploit Kit分析
    the beginner's guide to idapython
    一个windows下的ddos样本
    locky勒索样本分析
  • 原文地址:https://www.cnblogs.com/WineinSeptember/p/12750203.html
Copyright © 2011-2022 走看看