【问题标题】:Inserting nodes in a linked list in decreasing order - C按降序在链表中插入节点 - C
【发布时间】:2017-05-07 08:24:38
【问题描述】:

我必须制作一个列表,按人数递减的顺序排列人员(我的程序为“否”)。我试图通过修改addNode 函数来实现它,但我没有得到任何结果(人们不按他们的号码排列)。这是我的代码:

标题代码:

#ifndef __EX__
#define __EX__

typedef struct Person{
    char name[10];
    float no;
    struct Person *pNext;
} NODE, *pNODE, **ppNODE;

void addNode(ppNODE, pNODE);

void travers(pNODE, unsigned int*);


#endif

函数文件夹:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>

#include "EX.h"

void addNode (ppNODE ppPrim, pNODE p){
    pNODE q = (pNODE)malloc(sizeof(NODE));
    assert(q!=NULL);

    printf("Add name: \n");
    scanf("%s", &q->name);


    printf("\nAdd no: ");
    scanf("%f", &q->no);


    if (p == NULL || q->no < p->no) {
        q->pNext = *ppPrim;
        *ppPrim = q;
    } else {
            q->pNext = p->pNext;
            p->pNext = q;

    }
    return;
}


void travers(pNODE pPrim, unsigned int *pLen){
    *pLen = 0;
    pNODE tmp = pPrim;


    while (tmp != NULL){
        puts (tmp->name);
        fprintf(stdout, " no %.2f\n", tmp->no);
        tmp = tmp->pNext;
        (*pLen)++;
    }

    return;
}

主文件夹:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>

#include "EX.h"

int main(){
    unsigned int len;
    pNODE prim = NULL;
    int i;

    for (i=0; i<=1; i++){
        addNode(&prim, prim);
        addNode(&prim, prim->pNext);
    }

    travers(prim, &len);

    return 0;
}

【问题讨论】:

  • 你是不是已经在调试器中一步步执行了代码? main() 中的 for 循环看起来有点奇怪 - 我假设您在搜索错误时这样做了...
  • 您只需要使用插入排序将您的列表视为优先队列。检查this

标签: c sorting linked-list


【解决方案1】:

向列表中插入新节点时,必须遍历列表,直到找到合适的位置插入。您的代码采用第二个参数,这并不是真正需要的并且会导致混淆,并且只查看它。

head 定义的列表末尾插入代码q 的代码是:

Node *prev = NULL;
Node *p = *head;

while (p) {
    prev = p;
    p = p->pNext;
}

q->pNext = p;
if (prev == NULL) {
    *head = q;        
} else {
    prev->pNext = q;
}

您可以通过使用指向节点指针的指针遍历列表来摆脱对前一个节点的跟踪以及在头部插入和在其后插入之间的区别:

Node **p = &head;

while (*p && (*p)->no < q->no) {
    p = &(*p)->pNext;
}

q->pNext = *p;
*p = q;

在这段简洁的代码中,p 保存了最初的头地址和前一个节点的pNext 指针的地址。两者都可以通过*p更新。

您现在可以使用此代码遍历与每个节点关联的数字小于要插入的节点的数字。这是一个完整的程序:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef struct Node Node;
void addNode(Node **p, const char *name, float no);
void travers(Node *pPrim, unsigned int *pLen);

struct Node {
    char name[10];
    float no;
    Node *pNext;
};

void addNode(Node **p, const char *name, float no)
{
    Node *q = malloc(sizeof(*q));
    assert(q != NULL);

    snprintf(q->name, sizeof(q->name), "%s", name);
    q->no = no;

    while (*p && (*p)->no < q->no) {
        p = &(*p)->pNext;
    }

    q->pNext = *p;
    *p = q;
}

void traverse(const Node *pPrim, unsigned int *pLen)
{
    *pLen = 0;

    while (pPrim != NULL) {
        fprintf(stdout, "%-12s%.2f\n", pPrim->name, pPrim->no);
        pPrim = pPrim->pNext;
        (*pLen)++;
    }
}

int main()
{
    unsigned int len;
    Node *prim = NULL;

    addNode(&prim, "Alice",   0.23);
    addNode(&prim, "Bob",     0.08);
    addNode(&prim, "Charlie", 0.64);
    addNode(&prim, "Dora",    0.82);

    traverse(prim, &len);
    printf("\n%u entries.\n", len);

    return 0;
}

要节点的东西:

  • 我使用了Node *Node **,而不是类型化的pNODEppNODE。在我看来,使用 C 指针语法更清晰。
  • 您应该将获取用户输入与添加节点分开。
  • 在您的代码中,您不应在扫描字符串时传递 char 数组的地址,而应仅传递 char 数组。 (它恰好工作,但它不正确。编译器应该警告你。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-28
    • 2019-04-26
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 2021-08-23
    • 2011-08-13
    • 2015-10-20
    相关资源
    最近更新 更多