我在 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;
}
函数 max
和 insert
的名称具有误导性。 max
没有返回最大值,insert
没有让列表变长。更常见的是将这些函数分别命名为 siftDown
和 siftUp
,或类似的名称。
我的 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;
}
函数 max
和 insert
的名称具有误导性。 max
没有返回最大值,insert
没有让列表变长。更常见的是将这些函数分别命名为 siftDown
和 siftUp
,或类似的名称。