2017-05-07 58 views
0

我必须创建一个按人数顺序排列的人员列表(对于我的程序为“no”)。我试图通过修改addNode函数来实现,但我没有得到任何结果(人们不按他们的编号排列)。这是我的代码:按递减顺序在链表中插入节点 - C

页眉代码:

#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; 
} 
+0

你已经在调试器中一步一步地执行了代码吗? 'main()'中的for循环看起来有点奇怪 - 我假设你在搜索错误时执行了这个操作... – Scheff

+0

所有你需要的就是使用Insertion Sort来将你列为优先级队列。检查[this](http://stackoverflow.com/questions/25437682/use-a-linked-list-to-implement-a-priority-queue) –

回答

2

当你插入一个新节点添加到列表中,你必须遍历列表直到找到一个合适的地方插入它。你的代码需要第二个参数,这并不是真正需要的,会引起混淆,只会看到这个参数。

在列表的末尾由其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保持头中的第一地址和的地址前一个节点的指针。两者都可以通过*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 **代替typedeffed pNODEppNODE的。在我看来,使用C指针语法更清晰。
  • 您应该单独从添加节点中获取用户输入。
  • 在你的代码中,当扫描一个字符串时,不应该传递char数组的地址,而只能是char数组。 (它正常工作,但它不正确,编译器应该会提醒你)