简体   繁体   English

我的数组的值正在以意外的方式更改

[英]The values of my array are changing in an unexpected way

#define HEAP_MAX_SIZE 100
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

int size;
int heap[HEAP_MAX_SIZE];
int printcounter=0;

void swap(int *a, int *b)
{
    int temp = *b;
    *b = *a;
    *a = temp;  
}
/*
*max_heap() performs creates a max heap. (the printf in comments were used for debugging)
*/
void max_heap(int key)
{
    int leftkey = (2*key) +1;
    int rigtkey = (2*key) +2;
    //printf("key is: %d left child index is: %d right child index is: %d \n", key, leftkey, rigtkey);  
    //printf("value at key is: %d left child is: %d right child is: %d \n", heap[key], heap[leftkey], heap[rigtkey]);
    if (key >= 0){
        if (leftkey < size && leftkey != size){
            if (heap[leftkey] > heap[key]){ printf("If %d > %d\n", heap[leftkey], heap[key]);

                    printf("Swap %d and %d\n", heap[leftkey], heap[key]); 
                    swap(&heap[leftkey], &heap[key]);
                    max_heap(key+1);
            }
        }
        if (rigtkey < size && rigtkey != size){ 
            if (heap[rigtkey] > heap[key]){ printf("If %d > %d\n", heap[rigtkey], heap[key]);       

                    printf("Swap %d and %d\n", heap[rigtkey], heap[key]);                   
                    swap(&heap[rigtkey], &heap[key]);
                    max_heap(key+1);
            }
        }
        if (heap[leftkey] < heap[key] && heap[rigtkey] < heap[key]){
            max_heap(key-1);
        }

    }
}

/**
 * heapDelete() removes the biggest integer in the heap and returns it.
 *
 */
int heapDelete()
{
    int largest;    
    int i;  

    max_heap(size/2);
    largest = heap[0];

    ///Shifting the array so the first value is gone. (Should have used a link list instead of an array)
    for (i=0;i<size;i++){
        heap[i] = heap[i+1];
    }       
    size--; 
    printf("Just deleted: %d\n", largest);
    return largest;
}


/**
 *  addHeap(thing2add) adds the "thing2add" to the Heap.
 *
 */
void addHeap(int thing2add)
{   
    if (size == HEAP_MAX_SIZE)
    {
        fprintf(stderr, "Inputing too many values, increase HEAP_MAX_SIZE in intHeap.ca\n");
    }
    else
    {  
        heap[size] = thing2add;
        size++; 
    }
}

the heap array is {1 5 68 56 2 13 8 5 4 6 3 58 4 3 21 5} 堆数组是{1 5 68 56 2 13 8 5 4 6 3 58 4 3 21 5}

Just deleted: 1 刚删除:1

If 21 > 5 如果21> 5

Swap 21 and 5 交换21和5

If 58 > 13 如果58> 13

Swap 58 and 13 掉期58和13

If 4 > 2 如果4> 2

Swap 4 and 2 交换4和2

.... (you get the idea).... ....(您的想法)....

Just deleted: 4 刚删除:4

Just deleted: 4 刚删除:4

Just deleted: 3 刚删除:3

Just deleted: 3 刚删除:3

Just deleted: 2 刚删除:2

The swaps are fine, the deletes are fine. 交换很好,删除也很好。 However the 1 is being ignored. 但是1被忽略。 Plus the program should finish max_heap() before saying its first "deleted:" printf. 另外,该程序应在说出它的第一个“已删除:” printf之前完成max_heap()。 Why is it doing the printf first? 为什么要先执行printf? Does it have something to do with stdder? 它和stdder有关吗?

this doesn't happen all the time though. 但是,这并非始终都会发生。 If I enter a small set like:1 5 89 23 4 or 100 5 9 4 56 8 the program works as it should. 如果我输入一个小集合,例如:1 5 89 23 4或100 5 9 4 56 8,该程序将按预期运行。

Here's the main: 这是主要的:

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

extern int pop();
extern void push(int);
extern void addHeap(int);
extern int heapDelete();
extern void printHeap();

int main(int argc, char * argv[])
{
    int value;
    int size=0;
    int i=0;
    while (scanf("%d\n", &value) != EOF) {
        fprintf(stderr, "READING INPUT: %d\n", value);
        size++;
        addHeap(value); 
    }
    /*to print the heap in XML format*/

    printHeap();

    /*Print ends here*/

    /*print the heap in descending order, followed by ascending order (by pushing and popping from a stack)*/
    for (i=0;i<size;i++){
        push(heapDelete());
    }
    for (i=0;i<size;i++){
        printf("%d ", pop());
    }

    exit(0);
    /*Decsending and Ascending order ends here*/
}

I have played arround with your code and one thing to notice is the parent , left child and right child must be continuous to work: 我已经对您的代码进行了综合处理,需要注意的一件事是parentleft childright child必须连续工作:

parent      at position  i
left child  at position  i + 1
right child at position  i + 2

Also in your example {1 2 3} the output must be sorted also {3 2 1} not {3 1 2} . 同样在您的示例{1 2 3} ,输出也必须也排序为{3 2 1}而不是{3 1 2}

So, if you change 所以,如果你改变

int leftkey = (2 * key) + 1;
int rigtkey = (2 * key) + 2;

to

int leftkey = key +1; 
int rigtkey = key +2;

it works as expected 它按预期工作

valter 瓦尔特

It's not the size of the set causes the problem, for example, your code didn't work for {1 2 5 2} . 不是集合的大小会导致问题,例如,您的代码不适用于{1 2 5 2} The heapsort is done by two steps generally: 通常,通过两个步骤完成堆排序:

  • build a heap 建立一个堆
  • swap the max into its correct position, the swap disrupts the heap, then heapify the rest. 将最大值交换到正确的位置,交换会破坏堆,然后堆放其余的堆。

your max_heap() just performs heapifying (can't understand your implementation fully), not creating a max heap. 您的max_heap max_heap()仅执行堆化(无法完全理解您的实现),而不创建最大堆。 It seems you are using a " siftUp " version of heapify which has O(n log n) time complexity, while the "siftDown" version of heapify only has O(n) time complexity. 看来您正在使用的堆化的“ siftUp ”版本具有O(n log n)时间复杂度,而堆化的“ siftDown”版本仅具有O(n)时间复杂度。
Add the procedure of building the heap, your heapsort will work with correct heapify operation. 添加构建堆的过程后,您的堆排序将与正确的heapify操作一起工作。

//build a heap first!
for (i=0; i<size; i++){
    push(heapDelete());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM