如何按降序排列每个单词的出现次数?
我目前的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#define WORDLEN 50
typedef struct node_struct NODE;
struct node_struct {
char *word;
int count;
NODE *next;
};
/*compare and adds words to the list*/
NODE *new_node(char *word, NODE *head) {
NODE *p = head;
char *s;
if (p == NULL) {
p = (NODE*)malloc(sizeof(NODE));
s = (char*)malloc(sizeof(strlen(word) + 1));
strcpy(s, word);
p->word = s;
p->count = 1;
p->next = head;
return p;
}
for (; p->next != NULL && strcmp(p->word, word) != 0; p = p->next);
if (strcmp(p->word, word) == 0) {
p->count += 1;
return head;
}else{
p->next = (NODE*)malloc(sizeof(NODE));
p = p->next;
s = (char*)malloc(sizeof(strlen(word) + 1));
strcpy(s, word);
p->count = 1;
p->word = s;
p->next = NULL;
return head;
}
}
/*gets words*/
char *getword(char *w, int n)
{
int i = 0;
int c;
if (n <= 0 || feof(stdin))
return NULL;
c = getchar();
while (c != EOF && ! isalpha(c)) {
c = getchar();
}
if (c == EOF)
return NULL;
while (isalpha(c)) {
if (i < n - 1) {
w[i] = toupper(c);
i++;
}
c = getchar();
}
w[i] = '\0';
return w;
}
/*print*/
void print(NODE *p) {
for (; p != NULL; p = p->next) {
printf("%s %d\n",p->word, p->count);
}
printf("\n");
}
int main()
{
char w[WORDLEN];
NODE *p = NULL;
int i;
while (getword(w, WORDLEN) != NULL) {
p = new_node(w, p);
}
print(p);
return 0;
}
答案 0 :(得分:1)
您可以使用任何排序算法对链接列表进行排序。你可以在维基百科上找到排序算法的解释。以下是一些最简单的排序算法
这些维基百科页面也包含这些算法的伪代码,所以它应该非常直接地将这些算法翻译成C.你的起点是main()中的“P”,即你可以使用这些算法来升序或者降序。
答案 1 :(得分:0)
这个问题有点含糊不清 - 您想了解一下排序功能还是只想让程序运行? : - )
如果您只是想要一些有用的东西,您可以考虑使用动态扩展数组而不是链接列表。这样,您可以在添加新条目时重新分配(),并使用正常的qsort()
进行排序作为副作用,与使用链接列表相比,您可能还会看到更少的内存碎片,这可能会对整体性能产生很好的影响 - 特别是如果您执行的重新分配越来越少。代码也将更紧凑,可以提高可读性。
更新:啊,我无法抗拒表达我的意思。如果使用动态扩展数组,函数new_node可以像这样实现:
NODE * nodes = NULL;
unsigned node_count = 0;
void new_node(char word) {
unsigned n;
for (n = 0; n < node_count && strcmp(nodes[n], word) != 0; n++);
if (n < node_count) {
nodes[n].count++;
} else {
nodes = realloc(nodes, sizeof(NODE) * node_count + 1);
assert(nodes != NULL);
nodes[n].word = strdup(word);
assert(nodes[n].word != NULL);
nodes[n].count = 1;
}
}
如果您喜欢这个或不是个人喜好的问题。如果这是可用或不是真的取决于用例。
答案 2 :(得分:0)
我终于设法解决了,谢谢大家的帮助!
我的代码现在是:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#define WORDLEN 50
typedef struct node_struct NODE;
struct node_struct {
char *word;
int count;
NODE *next;
};
void new_node(char *word, NODE **head);
void print(NODE *p);
void mergesort_node(NODE **head);
void split_list(NODE *source, NODE **p, NODE **q);
NODE *merge_sorted_lists(NODE *source1, NODE *source2);
char *getword(char *word);
int main(int argc, char *argv[])
{
char w[WORDLEN];
NODE *p = NULL;
while (getword(w)) {
new_node(w, &p);
}
mergesort_node(&p);
print(p);
return 0;
}
//adds words to the list
void new_node(char *word, NODE **head) {
NODE *p = *head;
char *s;
if (p == NULL) {
p = (NODE*)malloc(sizeof(NODE));
s = (char*)malloc(sizeof(strlen(word) + 1));
strcpy(s, word);
p->word = s;
p->count = 1;
p->next = NULL;
*head = p;
}else{
for (; p->next != NULL && strcmp(p->word, word) != 0; p = p->next);
if (strcmp(p->word, word) == 0) {
p->count += 1;
}else{
p->next = (NODE*)malloc(sizeof(NODE));
p = p->next;
s = (char*)malloc(sizeof(strlen(word) + 1));
strcpy(s, word);
p->count = 1;
p->word = s;
p->next = NULL;
}
}
}
//gets words
char *getword(char *w)
{
int i = 0;
int c;
if (WORDLEN <= 0 || feof(stdin)){
return NULL;}
c = getchar();
while (c != EOF && ! isalpha(c)) {
c = getchar();
}
if (c == EOF)
return NULL;
while (isalpha(c)) {
if (i < WORDLEN - 1) {
w[i] = toupper(c);
i++;
}
c = getchar();
}
w[i] = '\0';
return w;
}
//print
void print(NODE *p) {
for (; p != NULL; p = p->next) {
printf("%s %d\n",p->word, p->count);
}
printf("\n");
}
//mergesort
void mergesort_node(NODE **head) {
NODE *p, *q, *newhead;
newhead = *head;
if (newhead == NULL || newhead->next == NULL) {
return;
}
split_list(newhead, &p, &q);
mergesort_node(&p);
mergesort_node(&q);
*head = merge_sorted_lists(p, q);
}
//Splits list in middle, using fast/slow method
void split_list(NODE *source, NODE **p, NODE **q) {
NODE *f, *s;
s = source;
f = source->next;
while (f != NULL) {
f = f->next;
if (f != NULL) {
s = s->next;
f = f->next;
}
}
*p = source;
*q = s->next;
s->next = NULL;
}
//Merges two individually sorted lists into one sorted list.
NODE *merge_sorted_lists(NODE *source1, NODE *source2) {
NODE *p, *q, *e, *newhead;
p = source1;
q = source2;
e = newhead = NULL;
while (p != NULL && q != NULL) {
if (p->count >= q->count) { //Compares the top items from the lists,
if (e == NULL) { //and puts the largest as next in the new list.
e = p;
newhead = e;
}else{
e->next = p;
e = e->next;
}
p = p->next;
}else if (p->count < q->count) {
if (e == NULL) {
e = q;
newhead = e;
}else{
e->next = q;
e = e->next;
}
q = q->next;
}
}
if (p == NULL) { //If one list ends, the rest of the other is added to the new list.
if (e == NULL) {
e = q;
newhead = e;
}else{
e->next = q;
}
}else if (q == NULL) {
if (e == NULL) {
e = p;
newhead = e;
}else{
e->next = p;
}
}
return newhead;
}