C - 根据值移动或删除多个节点

时间:2015-12-17 17:44:00

标签: c arrays pointers linked-list

我正在尝试为圣诞老人制作节目!我的知识有限;我迷失在指针和循环等中,我已经想了几个小时。

我有一组指向单链表的指针。每个数组索引都表示0:0-3,1:4-7,2:8-11,3:11-15的年龄组中的子项列表。

每个孩子都是一个结构,现在每年我想要浏览所有列表,将他们的年龄增加1,如果他们需要更改年龄组,我必须将节点移动到适当的列表中那个年龄组。如果孩子超过15岁,则必须删除该节点。我的代码不完整,因为我是链接列表的新手,我感到很困惑。

我的主要问题是我在浏览列表时对列表进行了更改,所以如果我检查第一个节点并将其删除,我必须再次检查第一个节点,因为现在它是一个新节点,所以我继续检查直到头部没问题,这是正确的方法吗?我不确定我的代码是否有效,我还无法测试它。

我的Santa_Claus.h中的部分:

/*Structure defining a node of the children list*/
struct child {
    int cid; /*The identifier of the child.*/
    int age; /*The age of the child.*/
    int did; /*The identifier of the child.*/
    int present_choices[M]; /*The array in which the preferences of the child for presents are stored*/
    struct child *next; /* Singly-linked, sorted by id */
};

来自Santa_Claus.c的部分

#define N 4 /*Number of children's age categories*/
struct child *Age_categories[N];

int new_season(void) {
    int i;
    struct child *childP = NULL;
    struct child *prev = NULL;
    struct child *childptr = NULL;
    int MaxAges[N] = {3,7,11.15};

    //Increment Age Loop
    for(i = 0; i < N; i++){

    childP = Age_categories[i];
        while(childP != NULL){
            childP->age = childP->age + 1;
            childP = childP->next;
        }
    }

    //Remove or Move Loop
    for(i = 0; i < N; i++){
        childP = Age_categories[i];

        //while the first is still > than the max age of this category
        while(childP->age > MaxAges[i]){
                if(i != (N-1)){
                    childP->next = Age_categories[i+1];
                    Age_categories[i+1] = childP;
                }else{
                    Age_categories[i] = childP->next;
                }
                childP = childP->next;
        }



        prev = Age_categories[i];
        childP = prev->next;

        while(childP != Null){

            if(childP->age > MaxAges[i]){
                if(i != (N-1)){
                    prev->next = childP->next;
                    childP->next = Age_categories[i+1];
                    Age_categories[i+1] = childP;
                }else{
                    Age_categories[i] = childP->next;
                }

            }
            prev = childP;
            childP = childP->next;
        }

    }

    return 1;
}

2 个答案:

答案 0 :(得分:0)

  

我的主要问题是我在浏览列表时对列表进行了更改,所以如果我检查第一个节点并将其删除,我必须再次检查第一个节点,因为现在它是一个新节点,所以我继续检查直到头部没问题,这是正确的方法吗?

在适当的位置编辑会咬你的边缘情况。你会遇到头部和尾部节点的问题。如果你移开头部,那么现在跟踪你的头部的任何东西都指向nullspace。

简而言之,你必须要小心。搞砸了很多方法。而对于新手来说,我建议你远离C中的指针。强大,但屁股很痛苦。坚持固定阵列,除非你真的需要这个东西来扩展。

您不需要重新检查头部,只需要检查头部的特殊情况,并进行头部安全编辑。同时检查该组是否为空,并检查尾部通常是好主意。你可以尝试找出一些聪明的东西,以避免这种事情,并有光滑的代码来处理所有...但聪明的代码经常咬你的屁股同样多。

答案 1 :(得分:0)

  

我的主要问题是我在浏览过程中对列表进行了更改   他们,所以如果我检查第一个节点并将其删除,我必须这样做   再次检查第一个节点,因为它现在是一个新节点,所以我保留   检查直到头部没问题,这是正确的方法吗?

原则上它是正确的方法,但你必须不仅为头部而且为每个列表中的每个节点做到这一点。您的代码并非适用于所有情况,例如:克。

        //while the first is still > than the max age of this category
        while(childP->age > MaxAges[i]){
                if(i != (N-1)){
                    childP->next = Age_categories[i+1];
                    Age_categories[i+1] = childP;
                }else{
                    Age_categories[i] = childP->next;
                }
                childP = childP->next;
        }
如果让我们说0岁组的头童已经4岁,那么

构成了一个无限循环。

考虑这个正确的代码,这个代码更短,因此错误的机会更少:

    // Remove or Move Loop
    for (i = 0; i < N; i++)
    {
        struct child **chPA;    // address of pointer to node under check
        // for each node in age group i
        for (chPA = &Age_categories[i]; childP = *chPA; )
            if (childP->age > MaxAges[i])
            {
                *chPA = childP->next;   // remove node from this list
                if (i != N-1)
                {
                    struct child **chPA;    // address of pointer to node in next group
                    // find where in next group to insert the aged node
                    for (chPA = &Age_categories[i+1]; childptr = *chPA;
                         chPA = &childptr->next)
                        if (childptr->cid > childP->cid) break;
                    (*chPA = childP)->next = childptr;
                }
                else
                    free(childP);   // delete the grown out node
            }
            else
                chPA = &childP->next;   // proceed to next node
    }

(由于您的代码评论,它根据cid在下一个更高年龄组中插入一个节点

    struct child *next; /* Singly-linked, sorted by id */