【问题标题】:I cannot create a linked list in C我无法在 C 中创建链表
【发布时间】:2021-08-12 02:22:37
【问题描述】:

基本上,对于我的任务,我需要实现代码来进行霍夫曼编码。为此,我需要将输入作为字符串,然后创建一个字符列表及其频率。当有新角色时,我需要创建一个新节点。我曾尝试在 C 中这样做,但没有结果。当我尝试打印我的链接列表时,我根本无法获得任何输出。我相信我从一开始就未能创建列表。 我的 C 代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

struct node {
    char character;
    int frequency;
    struct node *next;
}head;

struct node *insert(int frequency, char character) {
    struct node *newNode = malloc(sizeof(struct node));
    newNode->character = frequency;
    newNode->character = character;
    return newNode;
}

void create_freq_list(struct node *initial, int str_size, char str[]) {
    int i;
    struct node *temp;
    bool has_node;
    for (i = 0; i < str_size; i++) {
        temp = initial;
        has_node = false;
        while (temp->next != NULL) {
            if (temp->character == str[i]) {
                has_node = true;
                temp->frequency++;
            }
            temp = temp->next;
        }

        if (has_node == false) {
            while (temp->next != NULL) {
                temp = temp->next;
                if (temp->next == NULL) {
                    temp->next = insert(0, str[i]);
                }
            }
        }
    }
}

int main() {
    struct node *temp;
    char str[100];
    gets_s(str, 100);
    create_freq_list(&head, 100, str);

    temp = &head;
    while (temp->next != NULL) {
        printf("'%c' : %d", temp->character, temp->frequency);
        temp = temp->next;
    }

    getch();
    exit(0);
}

【问题讨论】:

  • 必须是链表吗?对于已知元素数量的频率计数器,数组效果很好。
  • 你可以使用什么调试器?
  • 另外,如果你可以使用 C++,你瞧,somebody already did that。但是是的,John 可能是对的,字符只有这么多,这就是为什么以 char 为索引的数组效果很好的原因。
  • 除了将character 分配给frequency 之外,您的代码中的主要问题是您从未在insert 中将next 设置为null(这也是错误的命名)。
  • @dekaottoman:您可以通过点击分数下方的灰色复选标记来接受答案。

标签: c linked-list huffman-code


【解决方案1】:

您的代码中有多个问题:

  • 您对head 节点的处理不正确:head 应定义为node *,您应将其地址传递给create_freq_list()
  • insert() 函数中有错字:newNode-&gt;character = frequency;
  • 您不应该对超出空终止符的字符串字符进行迭代。
  • 输出循环不正确:它应该迭代while (head),而不是while (head-&gt;next)。按照编码,输出初始节点但无意义,忽略最后一个节点。

这是修改后的版本:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node {
    char character;
    int frequency;
    struct node *next;
};

struct node *insert(int frequency, char character) {
    struct node *newNode = malloc(sizeof(struct node));
    if (newNode != NULL) {
        newNode->frequency = frequency;
        newNode->character = character;
    }
    return newNode;
}

void create_freq_list(struct node **headp, const char str[]) {
    for (int i = 0; str[i]; i++) {
        struct node **tailp = *headp;
        struct node *temp;
        while ((temp = *tailp) != NULL) {
            if (temp->character == str[i]) {
                temp->frequency++;
                break;
            }
            tailp = &temp->next;
        }
        if (temp == NULL) {
            *tailp = insert(1, str[i]);
        }
    }
}

int main() {
    struct node *head = NULL;
    char str[100];
    gets_s(str, 100);
    create_freq_list(&head, str);

    for (struct node *temp = head; temp != NULL; temp = temp->next) {
        printf("'%c': %d\n", temp->character, temp->frequency);
    }

    getch();
    return 0;
}

请注意,使用包含 256 个元素的数组来计算字符频率要简单得多。

【讨论】:

    【解决方案2】:

    我可以提出一个变体,使用优秀的&lt;sys/queue.h&gt; 的宏 这不是一个标准的包含,但每个打包好的系统都应该有它。 好吧,它可能不像手动编码链表那样具有教学性,但它更安全;-) 查看man queue(或man LIST_INIT)以了解功能。

    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include <sys/queue.h>
    
    typedef LIST_HEAD(listhead, entry) nodes_t;
    
    typedef struct entry {
      char character;
      int frequency;
      LIST_ENTRY(entry) entries;
    } node_t;
    
    
    void insert(nodes_t *list, char character) {
      node_t *newNode = malloc(sizeof(node_t));
      if (newNode != NULL) {
        newNode->frequency = 1;
        newNode->character = character;
        LIST_INSERT_HEAD(list, newNode, entries);
      }
    }
    
    node_t *get_node(nodes_t *list, char character) {
      node_t *n;
      LIST_FOREACH(n, list, entries)
        if (n->character == character)
          return n;
      return NULL;
    }
    
    void create_freq_list(nodes_t *list, const char str[]) {
      node_t *n;
      for (int i = 0; str[i]; i++) {
        n = get_node(list, str[i]);
        if (n == NULL)
          insert(list, str[i]);
        else
          n->frequency++;
      }
    }
    
    void print_list(nodes_t *list) {
      node_t *n;
      LIST_FOREACH(n, list, entries)
        printf("'%c': %d\n", n->character, n->frequency);
    }
    
    
    int main(int argc, char* argv[]) {
      nodes_t list;
    
      if (argc != 2) {
        fprintf(stderr, "Usage: %s <string>\n", argv[0]);
        return -1;
      }
      
      LIST_INIT(&list);
      
      create_freq_list(&list, argv[1]);
    
      print_list(&list);
      
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-05-14
      • 2021-10-13
      • 1970-01-01
      • 2015-02-14
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      相关资源
      最近更新 更多