顺序表的连接储存(用链表实现)

 


 

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

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

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

 



以下单独给出链表逆序过程。
/*------------------------------------------
函数名: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;
}

 如有错误欢迎指正!!

 

原文地址:https://www.cnblogs.com/WineinSeptember/p/12750203.html