链表和指针的问题(C)

时间:2017-01-02 08:18:28

标签: c linked-list

我正在编写一个C程序,根据最大值对链表进行排序。我遇到了一个问题,当程序达到“prevPtr-> next = headPtr”时程序就会挂起。 我希望prevPtr-> next等于headPtr,如果prevPtr的总和大于headPtr的总和,那么程序就会挂起。

compareNodes()函数用于比较节点以查看newNode是否与链表中的任何其他结构具有相同的名称,然后它将添加总和。

sortSimilarNodes()函数用于根据每个结构的总和对节点进行排序。

结构如下:

  struct purchase {
        char name[30];
        double sum;

        struct purchase * next;
    } ;

        LOG * compareNodes(LOG * headPtr, char * name, char * price){
        .
        .
        .
            while (curPtr != NULL) {
                    if (strcmp(newNode->name, curPtr->name)==0) {
                        curPtr->sum += newNode->sum;
                        free(newNode);
                        similar = 1;

                        break;

                    }
                    //advance to next target
                    prevPtr = curPtr; 
                    curPtr = curPtr->next;
                }
                /*if (curPtr == NULL){
                    if(strcmp(newNode->name, prevPtr->name)==0){
                        prevPtr->sum += newNode->sum;
                        free(newNode);
                        similar = 1;
                    }
                }*/

                if (similar == 1){
                    headPtr = sortSimilarNodes(curPtr, headPtr);

                }
                else{
                    headPtr = sortNodes(newNode, headPtr);
                }

                return headPtr;
    }

    LOG * sortSimilarNodes(LOG * newPtr, LOG * headPtr){
        LOG * curPtr;
        LOG * prevPtr;

        if(headPtr->sum < newPtr->sum){

            newPtr->next = headPtr;
            return newPtr;
        }

        prevPtr = headPtr;
        curPtr = headPtr->next;
        while (curPtr == NULL){

        }
        while (curPtr != NULL){

            if(strcmp(curPtr->name, newPtr->name)==0){
                break;
            }
            prevPtr = curPtr; 
            curPtr = curPtr->next;
        } 
        return headPtr;

    }

This is the output of the program. 谢谢!

1 个答案:

答案 0 :(得分:0)

很难从你的代码中分辨出来,因为你还没有发布所有内容,但你似乎对链表有一些误解。特别是:

  • 除非您真正向列表中添加新节点,否则不需要新节点。这也意味着除了添加节点之外,您不会调用malloc。 (代码中没有malloc,但比较函数中有free。比较不涉及创建或销毁任何内容;只是意味着查看已存在的内容。)

    < / LI>
  • 第一点的必然结果是空列表中不应有节点,甚至虚节点也不应该。空列表是headNULL的列表。确保在创建新列表之前初始化所有头指针:

    LOG *head = NULL;      // empty list
    
  • 对列表进行排序时,列表的顺序已更改,旧标题无效。你可以通过返回新的头来迎合这个:

    head = sort(head);
    

    但这似乎是多余的,它似乎暗示两个指针可能不同。事实并非如此,因为旧的指针会指向排序列表中的某些内容,而不一定是它的头部。传递头指针的地址可能更好,以避免混淆:

    sort(&head);
    

排序链表可能很棘手。一种直接的方法是选择排序:找到具有最高值的节点,将其从原始列表中删除并将其添加到新列表的前面。重复,直到原始列表中没有更多节点。

n给出的列表前面添加新节点head非常简单:

n->next = head;
head= n;

head给出的列表末尾添加新节点需要更多参与:

LOG **p = &head;

while (*p) p = &(*p)->next;
*p = n;
n->next = NULL;

此处,p是指向当前节点*p的指针的地址。在遍历列表之后,该地址是head节点的地址(当列表为空时)或precedig节点的next指针的地址。

你可以通过保持一个prev指针来实现类似的东西,但指向指针的解决方案意味着你不必特别以一些额外的代价来处理没有前一个节点的情况&*运营商。

这样,你的排序程序就变成了:

void sortByName(LOG **head)
{
    LOG *sorted = NULL;

    while (*head) {
        LOG **p = head;      // auxiliary pointer to walk the list
        LOG **max = head;    // pointer to current maximum
        LOG *n;              // maximum node

        while (*p) {
            if (strcmp((*p)->name, (*max)->name) > 0) max = p;
            p = &(*p)->next;
        }

        n = *max;
        *max = (*max)->next;

        n->next = sorted;
        sorted = n;
    }

    *head = sorted;
}

如果要按总和排序,请将比较更改为:

            if ((*p)->sum > (*max)->sum) max = p;

像这样调用函数:

LOG *head = NULL;

insert(&head, "apple", 2.3);
insert(&head, "pear", 1.7);
insert(&head, "strawberry", 2.2);
insert(&head, "orange", 3.2);
insert(&head, "plum", 2.1);

sortByName(&head); 
print(head);
destroy(&head);

使用insertdestroyprint函数表示完整性:

void insert(LOG **head, const char *name, double sum)
{
    LOG *n = malloc(sizeof(*n));

    if (n) {
        snprintf(n->name, sizeof(n->name), "%s", name);
        n->sum = sum;

        n->next = *head;
        *head = n;
    }    
}

void destroy(LOG **head)
{
    LOG *n = *head;

    while (n) {
        LOG *p = n;

        n = n->next;
        free(p);
    }

    *head = NULL;
}

void print(LOG *l)
{
    while (l) {
        printf("%s: %g\n", l->name, l->sum);
        l = l->next;
    }

    puts("");
}