崔渭阳 2023-09-23 21:55 采纳率: 66.7%
浏览 11

C语言链表遍历问题(地址问题)


#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h> // 添加头文件以使用malloc和free函数
#define ERROR 0
#define OK 1
typedef int Status;//判断程序是否运行成功 0-失败 1-成功
typedef int Element;
typedef struct Node{
    Element data;
    struct Node* next;//结构体中不可以直接使用Node名字声明
}Node,LinkList;
//LinkList存储头地址
//初始化链表
Status initiList(LinkList *L) {
    L = (Node*)malloc(sizeof(Node));
    if (L == NULL) {
        exit;//申请内存失败
    }
    L->next = NULL;
    return OK;//申请内存成功
}
//获取元素功能,获取元素并返回给e变量
Status getList(LinkList *L, int i, Element e) {
    int j=1;//计数器,来计算遍历的位置
    LinkList* p;//声明一个指针来指向头结点
    p = L->next;//绕过头节点
    while (p && j < i) {//判断指针是否为空,为空就是空表,注:i与j判断之间不可以取等号,因为第i个位置的地址是在前一个结点的后继指针
        p = p->next;
        j++;
    }
    if (!p || j > i)return ERROR;//j>i,避免i<1时造成查找错误
    e = p->data;
}
//链表的插入 
/*
* 两种种情况
* 1.插中间
* 2.插末尾
*/
Status insertList(LinkList* L, int i, Element e) {
    LinkList *p=L;
    int j = 1;//计数从零开始计数
    //插中间
    while (p && j < i) {//遍历到插入位置的前一个地方
        p = p->next;
        j++;
    }
    if (!p || j > i) {
        return ERROR;
    }
    Node* s = (Node*)malloc(sizeof(Node));
    /*
    * 插入时需要注意先接后面,再接前面;若先接前面,后面部分就会丢失找不到
    */
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}
//查找元素
Node* findList(LinkList *L, Element e) {
    Node* p = L->next;
    while (p != NULL && p->data != e) {
        p = p->next;
    }
    return p;//若在遍历玩之前查到,返回该元素所在地址,若未查到返回NULL;
}
//删除单链表某一节点
Status deleteElem(LinkList *L, int i) {//此时的i指的是第i个元素,不包括头节点
    int j = 1;//计数器
    LinkList *p;//存储头结点
    p = L;
    /*
    * 由于不包括头结点,所以需要判断p->next是否为空(这里与插入功能需要区别开)
    */
    while (p->next && j < i) {
        p = p->next;
        j++;
    }
    if (p->next != NULL || j > i) {
        return ERROR;
    }
    LinkList *q = p->next;//删除第i个元素,但地址实际存储在i-1位置,所有释放的是p->next所指向的内存
    p->next = q->next;
    free(q);
    return OK;//删除成功
    /*
    * 插入功能while(p&&j<i)与删除功能while(p->next&&j<i)判断条件的理解(i代表的是元素的位置,不包括头结点)
    * 1.插入功能中只需要判断到第i-1位位置不是空,就可以直接插入元素
    * 2.删除功能则需要判断第i-1位的下一个元素不能为空,因为删除的目的就是释放那个位置内存,则需要判断i-1指的下一个结点(即next)
    *   不能为空,要不然删除毫无意义
    */
}
//删除全部元素
Status deleteAll(LinkList *L) {
    LinkList* p=L->next;
    LinkList* q;
    while (p) {
        q = p->next;
        free(p);
        p = q;
    }
    L->next = NULL;
    return OK;

}
//单链表的整表建立(使用随机数建立)
//1.头插法,顾名思义一直插在头后面
void creatList1(LinkList *L, int n) {
    LinkList *p;
    srand(time(0));//创建随机数
    for (int i = 0; i < n; i++) {
        p = (Node*)malloc(sizeof(Node));
        p->data = rand() % 100 + 1;
        p->next = L->next;
        L->next = p;
    }
}
//2.尾插法,类似于排队,一直后插
void creatList2(LinkList *L, int n) {
    LinkList *p,*r;
    r = L;
    srand(time(0));
    for (int i = 0; i < n; i++) {
        p = (Node*)malloc(sizeof(Node));
        p->data = rand() % 100 + 1;
        r->next = p;
        r = p;
    }
    r->next = NULL;
}
//遍历链表
void searchList(LinkList L) {
    LinkList * p = L.next;
    /*for (int i = 0; i < 20; i++) {
        printf("%d\n", p->data);
        p = p->next;
    }*/

    while (p != NULL) {
        printf("%d\n", p->data);
        p = p->next;
    }

    return OK;
}
int main() {
    LinkList L;//存储头元素
    int choice=0;
    int index=0;
    Element elem=0;
    while(OK) {
        printf("欢迎使用单链表系统\n");
        printf("1.初始化链表\n");
        printf("2.头插法创建链表\n");
        printf("3.尾插法创建链表\n");
        printf("4.删除指定元素\n");
        printf("5.删除所有元素\n");
        printf("6.查找指定元素(并返回位置)\n");
        printf("7.插入指定位置\n");
        printf("8.遍历链表\n");
        printf("9.获取某元素\n");
        printf("10.退出\n");
        scanf("%d", &choice);
        switch(choice) {
            case 1:
                initiList(&L),
                    printf("Successful initialization!\n");
                break;
            case 2:
                creatList1(&L, 20);
                printf("Creat List successfully!\n");
                break;
            case 3:
                creatList2(&L, 20);
                printf("Creat List successfully!\n");
                break;

            case 4:
                printf("输入要删除元素的位置\n");
                scanf("%d", &index);
                deleteElem( &L, index);
                printf("删除成功!");
                break;
            case 5:
                deleteAll(&L);
                printf("删除成功");
                break;
            case 6:
                printf("输入你想查找的元素(整数)\n");
                scanf("%d", &elem);
                Element* e = findList(&L, elem);
                printf("你所查找的元素地址为%p", e);
                break;
            case 7:
                printf("请输入你想插入的指的位置\n");
                scanf("%d", &index);
                printf("请输入你想插入的元素\n");
                scanf("%d", &elem);
                insertList(&L, index, elem);
                printf("insert successfully!\n");
                break;
            case 8:
                searchList(L);
                break;
            case 9:
                printf("请输入获取位置的元素\n");
                scanf("%d", &index);
                getList(&L, index, elem);
                printf("该位置元素为:%d", elem);
                break;
            case 10:
                return 0;
            default:
                break;

        }
    }
}

img

我这个遍历功能为什么错了

  • 写回答

2条回答 默认 最新

  • qzjhjxj 2023-09-24 00:55
    关注

    修改如下,改动处见注释,供参考:

    #define _CRT_SECURE_NO_WARNINGS 1
    #include <stdio.h>
    #include <stdlib.h> // 添加头文件以使用malloc和free函数
    #define ERROR 0
    #define OK 1
    typedef int Status;//判断程序是否运行成功 0-失败 1-成功
    typedef int Element;
    typedef struct Node{
        Element data;
        struct Node* next;//结构体中不可以直接使用Node名字声明
    }Node,LinkList;
    //LinkList存储头地址
    //初始化链表
    Status initiList(LinkList *L) {
        //L = (Node*)malloc(sizeof(Node));   // 修改
        //if (L == NULL) {                   // 修改
        //    exit;//申请内存失败            // 修改
        //}                                  // 修改
        L->next = NULL;
        return OK;//申请内存成功
    }
    //获取元素功能,获取元素并返回给e变量
    Status getList(LinkList *L, int i, Element& e) { //Status getList(LinkList *L, int i, Element e)
        int j=1;//计数器,来计算遍历的位置
        LinkList* p;//声明一个指针来指向头结点
        p = L->next;//绕过头节点
        while (p && j < i) {//判断指针是否为空,为空就是空表,注:i与j判断之间不可以取等号,因为第i个位置的地址是在前一个结点的后继指针
            p = p->next;
            j++;
        }
        if (!p || j > i) return ERROR;//j>i,避免i<1时造成查找错误
        e = p->data;
        return OK;      // 修改
    }
    //链表的插入 
    /*
    * 两种种情况
    * 1.插中间
    * 2.插末尾
    */
    Status insertList(LinkList* L, int i, Element e) {
        LinkList *p=L;
        int j = 1;//计数从零开始计数
        //插中间
        while (p && j < i) {//遍历到插入位置的前一个地方
            p = p->next;
            j++;
        }
        if (!p || j > i) {
            return ERROR;
        }
        Node* s = (Node*)malloc(sizeof(Node));
        /*
        * 插入时需要注意先接后面,再接前面;若先接前面,后面部分就会丢失找不到
        */
        s->data = e;
        s->next = p->next;
        p->next = s;
        return OK;
    }
    //查找元素
    Node* findList(LinkList *L, Element e) {
        Node* p = L->next;
        while (p != NULL && p->data != e) {
            p = p->next;
        }
        return p;//若在遍历玩之前查到,返回该元素所在地址,若未查到返回NULL;
    }
    //删除单链表某一节点
    Status deleteElem(LinkList *L, int i) {//此时的i指的是第i个元素,不包括头节点
        int j = 1;//计数器
        LinkList *p;//存储头结点
        p = L;
        /*
        * 由于不包括头结点,所以需要判断p->next是否为空(这里与插入功能需要区别开)
        */
        while (p->next && j < i) {
            p = p->next;
            j++;
        }
        if (p->next == NULL || j > i) {   //if (p->next != NULL || j > i)  修改
            return ERROR;
        }
        LinkList *q = p->next;//删除第i个元素,但地址实际存储在i-1位置,所有释放的是p->next所指向的内存
        p->next = q->next;
        free(q);
        return OK;//删除成功
        /*
        * 插入功能while(p&&j<i)与删除功能while(p->next&&j<i)判断条件的理解(i代表的是元素的位置,不包括头结点)
        * 1.插入功能中只需要判断到第i-1位位置不是空,就可以直接插入元素
        * 2.删除功能则需要判断第i-1位的下一个元素不能为空,因为删除的目的就是释放那个位置内存,则需要判断i-1指的下一个结点(即next)
        *   不能为空,要不然删除毫无意义
        */
    }
    //删除全部元素
    Status deleteAll(LinkList *L) {
        LinkList* p=L->next;
        LinkList* q;
        while (p) {
            q = p->next;
            free(p);
            p = q;
        }
        L->next = NULL;
        return OK;
     
    }
    //单链表的整表建立(使用随机数建立)
    //1.头插法,顾名思义一直插在头后面
    void creatList1(LinkList *L, int n) {
        LinkList *p;
        srand(time(0));//创建随机数
        for (int i = 0; i < n; i++) {
            p = (Node*)malloc(sizeof(Node));
            p->data = rand() % 100 + 1;
            p->next = L->next;
            L->next = p;
        }
    }
    //2.尾插法,类似于排队,一直后插
    void creatList2(LinkList *L, int n) {
        LinkList *p,*r;
        r = L;
        srand(time(0));
        for (int i = 0; i < n; i++) {
            p = (Node*)malloc(sizeof(Node));
            p->data = rand() % 100 + 1;
            r->next = p;
            r = p;
        }
        r->next = NULL;
    }
    //遍历链表
    void searchList(LinkList L) {
        LinkList * p = L.next;
        /*for (int i = 0; i < 20; i++) {
            printf("%d\n", p->data);
            p = p->next;
        }*/
     
        while (p != NULL) {
            printf("%d ", p->data);  //\n 修改
            p = p->next;
        }
        printf("\n");                //  修改
        return;  //return OK; 函数返回值为 void 没有值,直接 return; 即可   修改
    }
    int main() {
        LinkList L;//存储头元素
        int choice=0;
        int index=0;
        Element elem=0;
        while(OK) {
            printf("欢迎使用单链表系统\n");
            printf("1.初始化链表\n");
            printf("2.头插法创建链表\n");
            printf("3.尾插法创建链表\n");
            printf("4.删除指定元素\n");
            printf("5.删除所有元素\n");
            printf("6.查找指定元素(并返回位置)\n");
            printf("7.插入指定位置\n");
            printf("8.遍历链表\n");
            printf("9.获取某元素\n");
            printf("10.退出\n");
            scanf("%d", &choice);
            switch(choice) {
                case 1:
                    initiList(&L),
                    printf("Successful initialization!\n");
                    break;
                case 2:
                    creatList1(&L, 20);
                    printf("Creat List successfully!\n");
                    break;
                case 3:
                    creatList2(&L, 20);
                    printf("Creat List successfully!\n");
                    break;
                case 4: {
                    printf("输入要删除元素的位置\n");
                    scanf("%d", &index);
                    if (deleteElem(&L, index) == OK)     // 修改
                        printf("删除成功!\n");           // 修改
                    else                                 // 修改
                        printf("未找到要删除的元素!\n"); // 修改
                    break;
                }
                case 5:
                    deleteAll(&L);
                    printf("删除成功");
                    break;
                case 6:{
                    printf("输入你想查找的元素(整数)\n");
                    scanf("%d", &elem);
                    Node* e = findList(&L, elem); //Element* e = findList(&L, elem); 函数返回类型为 Node* 修改
                    if (e)                                                      // 修改
                        printf("你所查找的元素地址为%p,值为:%d\n", e, e->data); // 修改
                    else
                        printf("未找到!\n");                                   // 修改
                    break;
                }
                case 7: {
                    printf("请输入你想插入的指的位置\n");
                    scanf("%d", &index);
                    printf("请输入你想插入的元素\n");
                    scanf("%d", &elem);
                    if (insertList(&L, index, elem) == OK)  // 修改
                        printf("insert successfully!\n");
                    else
                        printf("insert fail!\n");           // 修改
                    break;
                }
                case 8:
                    searchList(L);
                    break;
                case 9:
                    printf("请输入获取位置的元素\n");
                    scanf("%d", &index);
                    if (getList(&L, index, elem) == OK)     // 修改
                        printf("该位置元素为:%d\n", elem);  // 修改
                    else
                        printf("未找到该位置的元素!\n");    // 修改
                    break;
                case 10:
                    return 0;
                default:
                    break;
            }
        }
    }
    
    
    评论

报告相同问题?

问题事件

  • 创建了问题 9月23日

悬赏问题

  • ¥20 python忆阻器数字识别
  • ¥15 无法输出helloworld
  • ¥15 高通uboot 打印ubi init err 22
  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真