如果元素不在列表中,则在链接列表的开头添加元素

时间:2018-12-04 16:47:39

标签: c singly-linked-list

我具有以下数据结构:

typedef struct Word {
    char *word;
    int occur;
    struct Word *next_word;
} * WordList;

我正在尝试实现将字符串(单词)添加到WordList的功能。如果它已经存在于列表中,则增加它的出现次数,否则,将其添加到头部。此函数还返回列表中所说单词的出现。

接下来是我的实现方式

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

int addAtHead(WordList *w, char *word) {
    WordList head = *w;

    while (*w && strcmp((*w)->word, word) != 0)
        w = &(*w)->next_word;

    if (!*w) {
        WordList new = malloc(sizeof(struct Word));

        size_t length = strlen(word) + 1;
        new->word = malloc(length);
        memcpy(new->word, word, length);

        new->occur = 0;

        new->next_word = head;
        *w = new;
    }

    return ++(*w)->occur;
}

我具有以下这些功能来测试上一个功能:

#include <stdio.h>

void printWordList(WordList w) {
    for ( ; w; w = w->next_word)
        printf("Word: %s\nOccurrences: %d\n\n",
            w->word, w->occur);
}

int main(void) {
    WordList w = NULL;

    addAtHead(&w, "world");
    addAtHead(&w, "hello");
    printWordList(w);

    return 0;
}

当我编译并运行可执行文件时,会得到以下结果:

> Word: world Occurrences: 1
> 
> Word: hello Occurrences: 1
> 
> Word: world Occurrences: 1
> 
> Word: hello Occurrences: 1
> 
> Word: world Occurrences: 1
> 
> Word: hello Occurrences: 1

然后继续。

我假设我在代码中的某个地方将最后一个元素链接到第一个元素,因此我绘制了以下图表以找出发生这种情况的地方。

enter image description here

enter image description here

然后我假设问题出在*w = new;行中。 如何在不创建循环列表的情况下再次将*w设置为列表的开头?

1 个答案:

答案 0 :(得分:1)

我简化了您的代码……也许您会明白的:

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

typedef struct Word {
  char *word;
  int occur;
  struct Word *next_word;
}WordList;

int addAtHead(WordList **w_ptr, char *word) {
  WordList *head, *w;
  w = *w_ptr;
  head = w;

  while (w != NULL && strcmp(w->word, word) != 0)
     w = w->next_word;

  if (w == NULL) {
     WordList *newstruct;
     newstruct = malloc(sizeof *newstruct);
     if(newstruct == NULL) /* out of memory etc. */
       return -1;
     size_t length = strlen(word) + 1;
     newstruct->word = malloc(length);
     if(newstruct->word == NULL){
       free(newstruct);
       return -2;
     }
     memcpy(newstruct->word, word, length);

     newstruct->occur = 0;
     newstruct->next_word = head;
     w = newstruct;
     printf("address: %p, head: %p\n", w, head);
     *w_ptr = newstruct;
  }
  return ++(w->occur);
}

void printWordList(WordList *w) {
  for ( ; w; w = w->next_word)
     printf("Word: %s\nOccurrences: %d\n\n",
        w->word, w->occur);
}

int main(void) {
  int rv = 0;    
  WordList *w = NULL;

  rv = addAtHead(&w, "world");
  printf("addAtHead = %d\n",rv);
  rv = addAtHead(&w, "hello");
  printf("addAtHead = %d\n",rv);
  if(w == NULL){
    printf("w == NULL\n");
  } else { 
    printf("pointer address: %p\n",w);  
  }
  printWordList(w);
  return 0;
}

如果您想在函数中更改指针并想找回该更改后的指针,请执行以下操作:返回指针(该函数的构建类似于Wordlist * addAtHead(....),或者可以(在我们的情况下)使用指向该指针。您必须获得对该指针的引用。