- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
任务是为数组中未知类型的元素编写堆排序(仅使用 C 代码),但我的代码不起作用。对于以下数字输出是 '-100 7 -4 0 33 -3 67 1 5 44' 我也尝试将相同的代码仅用于 int 输入并且它工作得很好。所以我认为问题在于将其更改为任何类型的输入。
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <memory.h>
typedef int typeEl;
int compare(const void* a, const void* b)
{
return (*(typeEl*)a - *(typeEl*)b);
}
void swap(void* a, void* b, size_t sizeOfElem) {
void* tmp = calloc(1,sizeOfElem);
memcpy(tmp, a, sizeOfElem);
memcpy(a, b, sizeOfElem);
memcpy(b, tmp, sizeOfElem);
}
void heapify (int pos, int n, void* arr, size_t sizeOfElem, int (*comp)(const void* c, const void* d)) {
while (2 * pos + 1 < n) {
int t = 2 * pos +1;
if (2 * pos + 2 < n && ((char *)arr + (2*pos+2)*sizeOfElem) >= ((char *)arr + t*sizeOfElem))
{
t = 2 * pos + 2;
}
if (comp((void *) ((char *)arr + pos*sizeOfElem), ((char *)arr + t*sizeOfElem))<0) {
swap((void *) ((char *)arr + pos*sizeOfElem), (void *) ((char *)arr + t*sizeOfElem), sizeOfElem);
pos = t;
}
else break;
}
}
void heap_make(int n, void* arr, size_t sizeOfElem)
{
for (int i = n - 1; i >= 0; i--)
{
heapify(i, n, arr, sizeOfElem, compare );
}
}
void heap_sort(int n, void* arr, size_t sizeOfElem)
{
heap_make(n, arr, sizeOfElem);
while(n>0)
{
swap((void *) ((char *)arr), (void *) ((char *)arr + (n-1)*sizeOfElem), sizeOfElem);;
n--;
heapify(0,n, arr, sizeOfElem, compare);
}
}
int main() {
int n;
int m[10] = {1,-3,5,-100,7,33,44,67,-4, 0};
heap_sort(10, m, sizeof(int));
for (n=0; n<10; n++)
printf ("%d ",m[n]);
return 0;
}
谁能给个建议?感谢您的帮助!
最佳答案
解码别人的代码可能非常困难 - 特别是当您进行各种复杂的索引等操作时。我有一个 heapify 的旧副本(来自早期的答案 - https://stackoverflow.com/a/19749300/1967396),我修改了它适用于任何类型 - 并包括完整的排序。
这并没有完全回答“为什么您的代码不起作用”这个问题 - 但它确实向您展示了一些您在尝试回答该问题时可能想要实现的简单技术。通常,代码的可读性越高,调试就越容易。
请注意,为了提高可读性,我引入了几个额外的变量(和额外的代码行)- childLeft
和 childRight
绝对有用;此外,一旦为元素的指针建立了数据类型,就可以对元素进行索引 - 因为代码开头有 typedef
,所以我通过以下方式简化了一些事情
typeEl *array;
之后我可以用
索引数组array[pos];
这比
更具可读性(因此更不容易出错)*((void *) ((char *)arr + pos*sizeOfElem))
我还根据数组和需要交换的两个元素的索引定义了 swap
:
void swap(typeEl *arr, int i, int j)
这再次使代码更具可读性(另请注意,我不必执行 calloc
)。
无论如何 - 这是代码:
#include <stdio.h>
// define the type of the array that will be sorted:
typedef double typeEl;
void buildHeap(typeEl array[], int n);
void heapify(typeEl array[], int n, int i);
void heapsort(typeEl array[], int n);
void swap(typeEl array[], int indexA, int indexB);
void printTree(void);
int compare(typeEl a, typeEl b);
typeEl* TREE; // global variable used for printing the entire tree
int main(int argc, char *argv[])
{
typeEl heapArray[] = {1,-3,5,-100,7,33,44,67,-4, 0};
//{0, 1, 2, 3, 4, 5, 6 , 7, 8 ,9 ,10 , 11, 12, 13 ,14 ,15};
int n = sizeof(heapArray)/sizeof(typeEl);
TREE = heapArray;
printf("initial tree:\n");
printTree();
heapsort(heapArray, n);
printf("after heapify\n");
printTree();
printf("as a sorted array:\n");
for(int ii = 0; ii < n; ii++) printf("%d ", (int)heapArray[ii]);
printf("\n");
return 0;
}
void printTree(void)
{
// lazy way to print the entire tree...
typeEl* array = TREE;
printf(" %3d\n ", (int)array[0]);
printf(" %3d %3d\n", (int)array[1], (int)array[2]);
printf(" %3d %3d %3d %3d\n", (int)array[3], (int)(int)array[4], (int)array[5], (int)array[6]);
printf(" %3d %3d %3d\n", (int)array[7], (int)array[8], (int)array[9]);
printf("\n");
}
void heapsort(typeEl array[], int n) {
int i;
buildHeap(array, n);
for(i = 1; i < n; i++) {
buildHeap(array + i, n - i);
}
}
void buildHeap(typeEl array[], int n)
{
// change starting condition
int i = n/2;
while(i > 0) heapify(array, n,--i);
}
void heapify(typeEl array[], int n, int i)
{
// mark nodes initially as -1 to distinguish from "valid" zero
int childLeft = -1, childRight = -1;
int largest = i;
// see if we have valid child nodes:
if( 2 * i + 1 < n ) childLeft = 2 * i + 1;
if( 2 * i + 2 < n ) childRight = 2 * i + 2;
// see if any nodes are invalid now:
if(childLeft < 0 && childRight < 0) return;
if(childLeft < 0) childLeft = childRight; // can't happen, ever.
if(childRight < 0) childRight = childLeft;
// printf("child left [%i] = %i child right [%i] = %i\n", childLeft, array[childLeft], childRight, array[childRight]);
if (compare(array[childLeft], array[i] )) largest = childLeft;
if (compare(array[childRight] , array[largest])) largest = childRight;
if(largest != i)
{
swap(array, i,largest);
heapify(array, n, largest);
}
}
void swap(typeEl array[], int indexA, int indexB)
{
// printf("swap [%i] %i with [%i] %i\n", indexA, array[indexA], indexB, array[indexB]);
typeEl temp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = temp;
}
int compare(typeEl a, typeEl b) {
return (a - b>0)?1:0;
}
示例输出:
initial tree:
1
-3 5
-100 7 33 44
67 -4 0
after heapify
67
44 33
7 5 1 0
-3 -4 -100
as a sorted array:
67 44 33 7 5 1 0 -3 -4 -100
如您所见,它是从高到低排序的。显然,您可以通过简单地更改 compare
函数来更改它。
关于c - Heapsort 对任何类型的元素都不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20574404/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!