关于struct:C 带结构的双向链表

 2022-02-12 

C Doubly linked list with structure

我正在做一个双向链表。据我所知,它正在工作,但来到这里是为了确保并查看我是否以正确的方式进行操作。

另一方面,当我做这个时,我遇到了其他与双向链表无关的问题,但与 C 文件之间的结构和"可见性"有关。如果您了解我应该对这两个其他疑问提出其他问题,请告诉。否则请随时启发我。

在我的 file1.c 我有这个:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdio.h>
#include <stdlib.h>

typedef struct team{
    char *name;
    char *teamPlace;
}Team;

typedef struct nodeTeam{
    int numberOfTeams;
    Team team;
    struct nodeTeam *next;
    struct nodeTeam *prev;
}NodeTeam;

int createsListOfTeams(NodeTeam **head, NodeTeam **tail);
void printListOfTeams(NodeTeam *listofTeams);
int addNodeTeamsSorted(NodeTeam *head, NodeTeam **tail, Team team);

int main()
{
    NodeTeam *headEquipas,*tailEquipas;
    Team eq;
    /*Creates the doubly linked list*/
    if(createsListOfTeams(&headEquipas,&tailEquipas)){
        printf("\
Error\
"
);
        return 0;
    }
    /*Add the teams to the doubly linked list. At the end, all teams will be sorted by name*/
    eq.name ="D team";
    eq.teamPlace ="D team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\
Error\
"
);
        return 0;
    }

    eq.name ="A team";
    eq.teamPlace ="A team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\
Error\
"
);
        return 0;
    }

    eq.name ="C team";
    eq.teamPlace ="C team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\
Error\
"
);
        return 0;
    }

    eq.name ="B team";
    eq.teamPlace ="B team place";
    if (addNodeTeamsSorted(headEquipas,&tailEquipas,eq)){
        printf("\
Error\
"
);
        return 0;
    }

    /*Will print all the teams*/
    printListOfTeams(headEquipas);

    return 0;
}

在我的 file2.c 上有这个

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    typedef struct team{
        char *name;
        char *teamPlace;
    }Team;

    typedef struct nodeTeam{
        int numberOfTeams;
        Team team;
        struct nodeTeam *next;
        struct nodeTeam *prev;
    }NodeTeam;

    /*Add the teams to the doubly linked list. At the end, all teams will be sorted by name*/
    int createsListOfTeams(NodeTeam **head, NodeTeam **tail){
        (*head) = (NodeTeam *)malloc(sizeof(NodeTeam));

        if ((*head) == NULL){
            return -1;
        }
        (*head)->numberOfTeams = 0;
        (*head)->team.teamPlace ="";
        (*head)->team.name ="";
        (*head)->next = NULL;
        (*head)->prev = NULL;

        *tail = *head;
        return 0;
    }

    /*Creates the doubly linked list*/
    int addNodeTeamsSorted(NodeTeam *head, NodeTeam **tail, Team team){
        NodeTeam *no,*listIni;


        no = (NodeTeam*) malloc(sizeof(NodeTeam));
        if (no == NULL){
            return -1;
        }

        /*copy of my list*/
        listIni = head;

        no->team = team;
        /*to see is it's the first element of my list*/
        if(head->numberOfTeams == 0)
        {
            no->next = head->next;
            no->prev = head;
            head->next = no;
            *tail = no;

        }
        else{ /*If not the first element*/
            head = head->next;
            while(head->prev != *tail && strcmp(head->team.name,no->team.name) < 0 && strcmp((*tail)->team.name,no->team.name)>0){
                head = head->next;
                (*tail) = (*tail)->prev;
            }
            if(strcmp(head->team.name,no->team.name) >= 0 || head->prev == *tail){
                no->next = head;
                no->prev = head->prev;
                (head->prev)->next = no;
                head->prev = no;

            }
            else if(strcmp((*tail)->team.name,no->team.name) <= 0){
                no->next = (*tail)->next;
                no->prev = (*tail);
                (*tail)->next = no;
                *tail = no;

            }
        }

        /*Updates the number of element of the list*/
        head = listIni;
        head->numberOfTeams++;

        return 0;
    }
    /*Prints my lists*/
    void printListOfTeams(NodeTeam *listofTeams){
        printf("|   number of teams %22d |\
"
,listofTeams->numberOfTeams);
        printf("|      team name      |        team place      |\
"
);
        printf("--------------------------------------------------\
"
);
        listofTeams = listofTeams->next;
        while (listofTeams != NULL){
            printf("| %-21s | %-22s |\
"
,listofTeams->team.name,listofTeams->team.teamPlace);
            listofTeams = listofTeams->next;
        }
        printf("--------------------------------------------------\
\
"
);
    }

这是我的树问题:

Q1 - 这是实现双向链表的正确方法吗?头和尾分别指向列表的开头和结尾?

Q2 - 为什么要在我的两个文件上声明 struct teamstruct nodeTeam?既然它们都在同一个项目中,那么声明不应该对我项目中的所有文件都"可见"吗?

Q3 - 在 struct team 为什么我必须声明 char *name 而不是 char name[31]


在您之前的评论和更仔细地分析了您的代码之后,我做了一些修改。
我错误地解释了关于头部和尾部项目的一个评论,虽然你正在设计一个循环列表

  • 我花时间复制/粘贴/编译您的代码。虽然它几乎可以工作,但我必须说我会用

    以另一种方式设计

    • prev/ next 指针移动到 struct team
    • 并将 nodeTeamteam 成员替换为指向第一个 teamhead 指针。

    这将有以下好处:

    • 防止为每个 nodeTeams 重复但仅对第一个有意义的 numberOfTeams 浪费无用的空间
    • 避免概念上的 head 和实际的第一团队之间的混淆

    通过将团队列表中的指针值与

    相加

    printf("| %-21s | %-22s | %p - p=%p n=%p\
    ",listofTeams->team.name, listofTeams->team.teamPlace, listofTeams, listofTeams->prev, listofTeams->next);

    我注意到您的链接中可能存在错误:

    | A team | A team place | 0x101d00980 - p=0x101d00920 n=0x101d009e0

    | B team | B team place | 0x101d009e0 - p=0x101d00980 n=0x101d009b0

    | C team | C team place | 0x101d009b0 - p=0x101d00980 n=0x101d00950

    | D team | D team place | 0x101d00950 - p=0x101d009b0 n=0x0

    你可以看到next指针没问题,但是prev指针显示可疑重复(0x101d00920确实是'head')。

    如果您跟踪代码的执行并检查它在 addNodeTeamsSorted() 中所做的事情,您可能会注意到在第 3 步之前一切正常(在现有 A 之后添加团队 C