我正在进行K& R练习6-4,这是:
6-4。编写一个程序,在其输入中打印不同的单词,按照出现频率的降序排列。按其数量排在每个单词之前。
我决定做的是创建一个名为dstncFreqNode6_4的结构:
struct dstncFreqNode6_4
{
char *word;
int count;
struct dstncFreqNode6_4 *left;
struct dstncFreqNode6_4 *right;
};
然后我解析了单词的输入,并为每个不同的单词创建了一个“dstncFreqNode6_4”节点和两个指针:一个插入BST(添加新单词/更新已经遇到的单词的计数),和一个插入“dsntFredNode6_4”指针的全局数组。
这样做是为了通过遍历BST(其中包含到目前为止遇到的所有单词的指针)来更新单词(节点)的计数。解析完整个输入后,指针数组将按成员的“计数”变量排序,然后打印。
添加新单词/更新计数的代码在这里:(我认为它没有任何问题,因为BST和数组似乎是正确填充的,所以你可以忽略它)< / EM>:
//"wordCounts" is originally a global dstncFreqNode6_4** declared outside the function, numWords is the current length of the array
struct dstncFreqNode6_4 *addFreqNode6_4(struct dstncFreqNode6_4 *root, char *word)
{
if(root == NULL)
{
root = (struct dstncFreqNode6_4 *) malloc(sizeof(struct dstncFreqNode6_4));
root -> word = word;
root -> count = 1;
root -> left = NULL;
root -> right = NULL;
struct dstncFreqNode6_4 **p;
wordCounts = (struct dstncFreqNode6_4 **) realloc(wordCounts, sizeof(struct dstncFreqNode6_4*) * (numWords +1));
p = wordCounts + numWords++;
(*p) = root;
}
else if(strcmp(word, root -> word) < 0)
root -> left = addFreqNode6_4(root -> left, word);
else if(strcmp(word, root -> word) > 0)
root -> right = addFreqNode6_4(root -> right, word);
else
root -> count++;
return root;
}
所以除了排序之外我还能正常工作;它根本不会对数组进行排序。也就是说... 元素的顺序保持不变 编辑:我收到分段错误。 编辑#2: 现在没有分段错误;原来的问题仍然存在。
我正在使用stlib.h的qsort方法;我正在使用的比较功能是:
int qcmp6_4(const void *a, const void *b)
{
return (*(struct dstncFreqNode6_4 **)a) -> count - (*(struct dstncFreqNode6_4 **)b) -> count;
}
我似乎无法弄清楚为什么它不能正确排序。我实际上实现了自己的快速排序算法,并得到了相同的结果。我现在真的不知道。
让一些新鲜的,专业的眼睛指向正确的方向会很好。感谢。
修改
对不起,这是对qsort的调用:
qsort(wordCounts, numWords, sizeof(struct dstncFreqNode6_4 *), qcmp6_4);
编辑#2:
根据这个建议,我已经将“wordCounts”作为一个指向节点的指针数组(此帖子中的所有代码都已更新以反映此)。所以本质上,BST和数组包含相同的信息(实际上数组指针被初始化为BST中的相应指针),但它们的用途是不同的。 BST用于添加新单词/更新已经遇到的单词的数量,并且数组在末尾(通过每个单词'计数)排序并打印。但是,我遇到了我最初遇到的同样问题:在调用qsort之后,数组的顺序保持不变。
答案 0 :(得分:0)
在我看来,您正在尝试对节点数组进行排序,每个节点都包含指向数组中其他节点的指针。排序后,这些指针当然会指向数组的错误元素。也许那是你的问题?
顺便说一下,我看到你正在使用realloc
。每当必须将分配的数组移动到新位置以满足新的大小要求时,指向数组元素的指针就会出现realloc
,只会更糟糕:节点指针现在都将指向无效地址并使用它们将导致未定义的行为。
一种可能的解决方案是永远不要修改原始的节点数组,而是创建第二个指向节点的数组,并使用比较函数对指针数组进行排序,比较它们指向的节点到。
答案 1 :(得分:0)
所以我设法用自己的quicksort实现来排序。 stlib.h的版本仍然没有排序我的数组。它只能用于原始类型的数组吗?因为这是我能看到的阻止它工作的唯一原因。
这是我的自定义qsort代码供参考:
void swapFreq6_4(struct dstncFreqNode6_4 **a, struct dstncFreqNode6_4 **b)
{
struct dstncFreqNode6_4 *t=*a; *a=*b; *b=t;
}
void **sortFreq6_4(struct dstncFreqNode6_4 **arr, int beg, int end)
{
if (end > beg + 1)
{
struct dstncFreqNode6_4 *piv = *(arr + beg);
int l = beg + 1;
int r = end;
while (l < r)
{
if ( (*(arr + l))-> count <= piv -> count)
l++;
else
swapFreq6_4((arr + l), (arr + --r));
}
swapFreq6_4((arr + --l), (arr + beg));
sortFreq6_4(arr, beg, l);
sortFreq6_4(arr, r, end);
}
}
有谁知道为什么stdlib的qsort代码不适用于我的struct?我使用它错了(我对它的调用,以及比较功能都在原帖中)?