我在 C 中的二进制堆程序有问题

I am having a problem with my binary heap program in C

我的 C 程序有问题,由于某种原因它没有返回我正在寻找的正确结果。当我 运行 它显示两次指令然后说无效选择,即使我没有输入选择,当我做出选择时它不会输出我想要的结果,即使我相信代码没错

这是问题:

这是程序给出的输出: 代码如下:

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

int arr[100005];
int n;

void max(int index){
    if (index>=n)return;
    int left=2*index+1;
    int right = 2*index + 2;
    int mx_ind=index;
    if (left < n && arr[left]>arr[mx_ind]){
        mx_ind=left;
    }
    if (right < n && arr[left]>arr[mx_ind]){
        mx_ind=right;
    }
    if (mx_ind !=index){
    int tmp=arr[mx_ind];
    arr[mx_ind]=arr[index];
    arr[index]=tmp;
    max(mx_ind);
    }
}

int insert(int num,int location){
int p;
while (location>0)
{
    p=(location-1)/2;
    if(num>=arr[p])
    {
        arr[location]=arr[p];
    }
    else break;
    location=p;
    }
    arr[location]=num;
    return 0;
}


void del(int index){
arr[index]=arr[n-1];
n=n-1;
max(index);
}

void buildmaxheap(){
for (int i=n/2-1;i>=0;i--){
    max(i);
}
}


void display(){
for (int i=0;i<n;i++){
        printf("%d",arr[i]);
        printf("\n");
}
}
int returnmax(){
return arr[0];
}
int extractmax(){
int mx=arr[0];
del(0);
return mx;
}

int main()
{
    printf("enter num of elements");
    scanf("%d",&n);
    printf("enter value of elements");
    for(int i=0;i<n;i++){
        scanf("%d",&arr[i]);
    }
    buildmaxheap();
    int num,index;
    char choice;

    while(1){
     printf("1. extract max\n");
     printf("2. insert new key\n");
     printf("3. change key at A[i]\n");
     printf("4. delete key at A[i] \n");
     printf("5. return max\n");
     printf("6. exit\n");
     printf("Enter your choice:");
     scanf("%c",&choice);
     switch(choice)
     {
     case '1':
         printf("Max value is : %d\n", extractmax);
         break;

     case '2':
         scanf("%d",&num);
         insert(num,n);
         n++;
         printf("Content of array is:");
         display();
         break;

     case '3':
        scanf("%d %d",&index,&num);
         arr[index]=num;
         if (arr[(index-1)/2]>num)max(index);
         else insert(num,index);
         printf("content of array is : ");
         display();
         break;

     case '4':
         scanf("%d",&index);
         del(index);
         printf("Content of array is : \n");
         display();
         break;

     case '5':
         printf("Max value is : %d\n", extractmax);
         break;

     case '6':
         exit(1);
         break;
         default:printf("invalid choice\n");
     }
    }

return 0;
}

如有任何帮助,我们将不胜感激。

几个问题:

  • “无效选择”输出的发生是因为 choice 得到一个白色的 space(换行符)作为值。为避免选择白色 space,通过在 scanf 格式字符串前加上 space 来排除它:scanf(" %c", &choice)

  • max 中,您在第二个 if 条件中有一个错误。您应该使用 right 作为索引而不是 left

  • 对于某些操作,要求数组不为空。这应该检查以避免出现问题。

  • 在情况 3 中,当 index 为零时,表达式 arr[(index - 1) / 2] 无效。

此外,我建议当用户选择 6 时不要调用 exit(1),而是将其设置为 while 条件。

这是更正后的版本:

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

int arr[100005];
int n;

void max(int index) {
    if (index >= n) return;
    int left = 2 * index + 1;
    int right = left + 1; 
    int mx_ind = index;
    if (left < n && arr[left] > arr[mx_ind]) {
        mx_ind = left;
    }
    if (right < n && arr[right] > arr[mx_ind]) { // bug fix
        mx_ind = right;
    }
    if (mx_ind != index) {
        int tmp = arr[mx_ind];
        arr[mx_ind] = arr[index];
        arr[index] = tmp;
        max(mx_ind);
    }
}

int insert(int num, int location){
    int p;
    while (location > 0) {
        p = (location - 1) / 2;
        if (num >= arr[p]) {
            arr[location] = arr[p];
        }
        else break;
        location = p;
    }
    arr[location] = num;
    return 0;
}


void del(int index) {
    arr[index] = arr[n - 1];
    n--;
    max(index);
}

void buildmaxheap() {
    for (int i = n / 2 - 1; i >= 0; i--) {
        max(i);
    }
}


void display() {
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int returnmax() {
    return arr[0];
}

int extractmax() {
    int mx = arr[0];
    del(0);
    return mx;
}

int main() {
    printf("enter num of elements: ");
    scanf("%d", &n);
    printf("enter value of elements: ");
    for(int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    buildmaxheap();
    int num,index;
    char choice = ' ';

    while (choice != '6') { // Nicer to add the condition here
        // Maybe always start each iteration with this:
        printf("Content of array is: ");
        display();

        printf("1. extract max\n");
        printf("2. insert new key\n");
        printf("3. change key at A[i]\n");
        printf("4. delete key at A[i] \n");
        printf("5. return max\n");
        printf("6. exit\n");
        printf("Enter your choice: ");
        scanf(" %c", &choice); // Skip white space

        switch (choice) {
        case '1':
            if (n == 0) { // Add this protection
                printf("The array is empty\n");
            } else {
                // Should call the function
                printf("Max value is: %d\n", extractmax());
            }
            break;

        case '2':
            scanf("%d", &num);
            insert(num, n);
            n++;
            break;

        case '3':
            // Help the user:
            printf("Enter index and new value: ");
            scanf("%d %d", &index, &num);
            // Add this protection:
            if (index >= n) {
                printf("The array does not have this index\n");
            } else {
                arr[index] = num;
                // Add case for when index is 0
                if (index == 0 || arr[(index - 1) / 2] > num) max(index);
                else insert(num, index);
            }
            break;

        case '4':
            // Help the user:
            printf("Enter index: ");
            scanf("%d", &index);
            // Add this protection:
            if (index >= n) {
                printf("The array does not have this index\n");
            } else {
                del(index);
            }
            break;

        case '5':
            if (n == 0) { // Add this protection
                printf("The array is empty\n");
            } else {
                // Call the function, and the right one:
                printf("Max value is : %d\n", returnmax());
            }
            break;

        case '6':
            break; // Just break and use while condition to quit (no exit())

        default:
            printf("invalid choice '%c'\n", choice);
        }
    }

    return 0;
}

函数 maxinsert 的名称具有误导性。 max 没有返回最大值,insert 没有让列表变长。更常见的是将这些函数分别命名为 siftDownsiftUp,或类似的名称。