Tower of Hanoi – 为什么我的函数没有正确更新指针?

huangapple go评论73阅读模式
英文:

Tower of Hanoi - Why are my functions not updating the pointers correctly?

问题

The issue with your code appears to be related to how C++ handles pointers. When you pass a pointer to a function, you're passing a copy of the pointer, not the actual pointer itself. Therefore, when you modify the pointer within the swap_disk function, you're modifying a copy of the pointer, not the original pointer outside of the function.

To fix this issue, you should pass a pointer to a pointer (a double pointer) to the swap_disk function so that you can modify the original pointers. Here's how you can update your swap_disk function and its usage in tower_of_hanoi_solver:

void swap_disk(disk** swap_tower_a, disk** swap_tower_b)
{
    disk* top_tower_a = top_disk(*swap_tower_a);
    disk* top_tower_b = top_disk(*swap_tower_b);

    if (*swap_tower_a == NULL && *swap_tower_b == NULL)
    {
        return;
    }
    else if (*swap_tower_a != NULL && *swap_tower_b == NULL)
    {
        *swap_tower_b = push(*swap_tower_b, top_tower_a->value);
        *swap_tower_a = pop(*swap_tower_a);
    }
    else
    {
        if (top_tower_a != NULL && top_tower_b != NULL) {
            if (top_tower_a->value < top_tower_b->value)
            {
                *swap_tower_b = push(*swap_tower_b, top_tower_a->value);
                *swap_tower_a = pop(*swap_tower_a);
            }
            else
            {
                return;
            }
        }
    }
}

void tower_of_hanoi_solver(disk** tower1, disk** tower2, disk** tower3, int max_height)
{
    int tower_1_height = tower_height_recursive(*tower1);

    // Tower 1
    if (tower_1_height % 2 == 0)
    {
        swap_disk(tower1, tower2);
    }
    else
    {
        swap_disk(tower1, tower3);
    }

    // Tower 2
    swap_disk(tower2, tower3);
    swap_disk(tower2, tower1);

    // Tower 3
    swap_disk(tower3, tower2);
    swap_disk(tower3, tower1);

    int tower_3_height = tower_height_recursive(*tower3);

    if (tower_3_height == max_height)
    {
        return;
    }
    else
    {
        tower_of_hanoi_solver(tower1, tower2, tower3, max_height);
    }
}

With these changes, you're passing pointers to pointers to swap_disk, allowing you to modify the original pointers within the function, which should resolve the issue of the pointers not being updated as expected.

英文:

First, I defined most of my functions recursively to practice recursion.

When I looked at the debugger, I noticed several things:

  1. My functions swap() is NOT updating the pointer variables in the tower_of_hanoi() function
  2. My functions push() and pop() are not handling the exceptions.
  3. Since my swap() function is not updating my pointers, the base case is never reached.

I tried to catch several exceptions, but I notice that it still did not help. I was expecting each of the swap() calls to update the pointers, but it is not properly updating the pointer variables. So the height of my 3rd tower is ALWAYS a height of 0, and the problem is never solved.

Here is the code:

#include &lt;iostream&gt;
#include &lt;string&gt;

using namespace std;

struct disk {
	int value;
	disk* top;
};

// Initializing Structures
disk* tower_1 = NULL;
disk* tower_2 = NULL;
disk* tower_3 = NULL;
disk* tower_1_top = NULL;
disk* tower_2_top = NULL;
disk* tower_3_top = NULL;

// Function 
disk* push(disk* tower, int value); // push (disk* tower to push into, int value we want the disk to have)
void push_helper(disk* current_disk, disk* new_disk); 
disk* pop(disk* tower); // pop(disk* tower to pop off top disk)
disk* top_disk(disk* tower);
int tower_height(disk* tower);
int tower_height_recursive(disk* tower);
void display_tower(disk* tower);
void display_tower_recursive(disk* tower);
void swap_disk(disk* swap_tower_a, disk* swap_tower_b);
void tower_of_hanoi_solver(disk* tower1, disk* tower2, disk* tower3, int max_height);

int main()
{
	char user_continue = &#39;y&#39;;

	tower_1 = push(tower_1, 4);
	tower_1 = push(tower_1, 2);
	tower_1 = push(tower_1, 1);
	tower_1_top = top_disk(tower_1);

	cout &lt;&lt; &quot;Tower 1: \n&quot;;
	display_tower_recursive(tower_1);
	cout &lt;&lt; endl &lt;&lt; endl;
	cout &lt;&lt; &quot;Tower 1 Height: &quot; &lt;&lt; tower_height_recursive(tower_1) &lt;&lt; endl;
	cout &lt;&lt; &quot;Top of Tower 1: &quot; &lt;&lt; tower_1_top-&gt;value &lt;&lt; endl &lt;&lt; endl;


	cout &lt;&lt; &quot;Tower 2: \n&quot;;
	display_tower_recursive(tower_2);
	cout &lt;&lt; endl &lt;&lt; endl;
	cout &lt;&lt; &quot;Tower Height: &quot; &lt;&lt; tower_height_recursive(tower_2) &lt;&lt; endl &lt;&lt; endl;

	cout &lt;&lt; &quot;Tower 3: \n&quot;;
	display_tower_recursive(tower_3);
	cout &lt;&lt; endl &lt;&lt; endl;
	cout &lt;&lt; &quot;Tower Height: &quot; &lt;&lt; tower_height_recursive(tower_3) &lt;&lt; endl &lt;&lt; endl;



	// Call to do the Tower of Hanoi game
	int max_height_tower = tower_height_recursive(tower_1);
	tower_of_hanoi_solver(tower_1, tower_2, tower_3,max_height_tower);

	//Final Towers After Game
	cout &lt;&lt; &quot;Final Towers: \n\n&quot;;

	cout &lt;&lt; &quot;Tower 1: \n&quot;;
	display_tower_recursive(tower_1);
	cout &lt;&lt; endl &lt;&lt; endl;
	cout &lt;&lt; &quot;Tower Height: &quot; &lt;&lt; tower_height_recursive(tower_1) &lt;&lt; endl &lt;&lt; endl;

	cout &lt;&lt; &quot;Tower 2: \n&quot;;
	display_tower_recursive(tower_2);
	cout &lt;&lt; endl &lt;&lt; endl;
	cout &lt;&lt; &quot;Tower Height: &quot; &lt;&lt; tower_height_recursive(tower_2) &lt;&lt; endl &lt;&lt; endl;

	cout &lt;&lt; &quot;Tower 3: \n&quot;;
	display_tower_recursive(tower_3);
	cout &lt;&lt; endl &lt;&lt; endl;
	cout &lt;&lt; &quot;Tower Height: &quot; &lt;&lt; tower_height_recursive(tower_3) &lt;&lt; endl &lt;&lt; endl;


	cin.ignore();
	cin.get();
}

disk* push(disk* tower, int value)
{
	disk* p_new_disk = new disk;
	p_new_disk-&gt;value = value;
	p_new_disk-&gt;top = NULL;

	if (p_new_disk == NULL)
	{
		return NULL;
	}
	else if (tower == NULL)
	{
		tower = p_new_disk;
		return tower;
	}
	else 
	{
		if (tower-&gt;top == NULL)
		{
			tower-&gt;top = p_new_disk;
			return tower;
		}
		else if (tower-&gt;top-&gt;top == NULL)
		{
			tower-&gt;top-&gt;top = p_new_disk;
		}
		else
		{
			push(tower-&gt;top-&gt;top, value);
		}
		//push_helper(tower, p_new_disk);
	}
	

	return tower;
}

void push_helper(disk* current_disk, disk* new_disk)
{
	if (current_disk -&gt; top == NULL)
	{
		current_disk-&gt;top = new_disk;
	}
	else
	{
		push_helper(current_disk-&gt;top, new_disk);
	}
}

disk* pop(disk* tower)
{
	if (tower == NULL)
	{
		return NULL;
	}

	if (tower-&gt;top == NULL) 
	{
		return NULL;
	}
	else 
	{
		if (tower-&gt;top != NULL &amp;&amp; tower-&gt;top-&gt;top == NULL)
		{
			disk* p_temp = tower-&gt;top;
			tower-&gt;top = NULL;
			delete p_temp;
			return tower;
		}
		else
		{
			return pop(tower-&gt;top);
		}
	}

}

disk* top_disk(disk* tower)
{

	if (tower == NULL)
	{
		return NULL;
	}
	else if (tower-&gt;top == NULL)
	{
		return tower;
	}
	else
	{
		return top_disk(tower-&gt;top);
	}
}

int tower_height(disk* tower)
{
	disk* current_disk = tower;
	int count = 0;

	while (current_disk != NULL)
	{
		count++;
		current_disk = current_disk-&gt;top;
	}

	return count;
}

int tower_height_recursive(disk* tower)
{
	disk* current_disk = tower;

	if (current_disk == NULL) // Handles if the(current_disk has NO disks.
	{
		return 0;
	}
	else
	{
		return 1 + tower_height_recursive(current_disk-&gt;top);
	}
}

void display_tower(disk* tower)
{
	disk* current_disk = tower;
	while (current_disk != NULL)
	{
		cout &lt;&lt; current_disk-&gt;value &lt;&lt; endl;
		current_disk = current_disk-&gt;top;
	}
}

void display_tower_recursive(disk* tower)
{
	if (tower == NULL)
	{
		cout &lt;&lt; &quot;None!\n&quot;;
	}
	else
	{
		cout &lt;&lt; tower-&gt;value &lt;&lt; endl;
		display_tower_recursive(tower-&gt;top);
	}

}

void swap_disk(disk* swap_tower_a, disk* swap_tower_b)
{
	disk* top_tower_a = top_disk(swap_tower_a);
	disk* top_tower_b = top_disk(swap_tower_b);

	if (swap_tower_a == NULL &amp;&amp; swap_tower_b == NULL) 
	{
		return;
	}
	else if (swap_tower_a != NULL &amp;&amp; swap_tower_b == NULL)
	{
		swap_tower_b = push(swap_tower_b, top_tower_a-&gt;value);
		swap_tower_a = pop(swap_tower_a);
	}
	else
	{
		if (top_tower_a != NULL &amp;&amp; top_tower_b != NULL) {
			if (top_tower_a-&gt;value &lt; top_tower_b-&gt;value)
			{
				swap_tower_b = push(swap_tower_b, top_tower_a-&gt;value);
				swap_tower_a = pop(swap_tower_a);
			}
			else
			{
				return;
			}
		}
	}
	
}

void tower_of_hanoi_solver(disk* tower1, disk* tower2, disk* tower3, int max_height)
{
	int tower_1_height = tower_height_recursive(tower1);

	// Tower 1
	if (tower_1_height % 2 == 0)
	{
		swap_disk(tower1, tower2);
	}
	else
	{
		swap_disk(tower1, tower3);
	}

	// Tower 2
	swap_disk(tower2, tower3);
	swap_disk(tower2, tower1);

	// Tower 3
	swap_disk(tower3, tower2);
	swap_disk(tower3, tower1);

	int tower_3_height = tower_height_recursive(tower3);

	if (tower_3_height == max_height)
	{
		return;
	}
	else
	{
		tower_of_hanoi_solver(tower1, tower2, tower3,  max_height);
	}


}


I first defined my pointers to be global for the towers - tower_1, tower_2, and tower_3 - so my entire program can manipulate and change the value. I did not put the word 'const' in front of them.

I wanted the tower_of_hanoi_solver() function to use the swap() function, but my debugger says my pointers are not being updated. Here's the code for the swap() and tower_of_hanoi_solver() functions

void swap_disk(disk* swap_tower_a, disk* swap_tower_b)
{
	disk* top_tower_a = top_disk(swap_tower_a);
	disk* top_tower_b = top_disk(swap_tower_b);

	if (swap_tower_a == NULL &amp;&amp; swap_tower_b == NULL) 
	{
		return;
	}
	else if (swap_tower_a != NULL &amp;&amp; swap_tower_b == NULL)
	{
		swap_tower_b = push(swap_tower_b, top_tower_a-&gt;value);
		swap_tower_a = pop(swap_tower_a);
	}
	else
	{
		if (top_tower_a != NULL &amp;&amp; top_tower_b != NULL) {
			if (top_tower_a-&gt;value &lt; top_tower_b-&gt;value)
			{
				swap_tower_b = push(swap_tower_b, top_tower_a-&gt;value);
				swap_tower_a = pop(swap_tower_a);
			}
			else
			{
				return;
			}
		}
	}
	
}

void tower_of_hanoi_solver(disk* tower1, disk* tower2, disk* tower3, int max_height)
{
	int tower_1_height = tower_height_recursive(tower1);

	// Tower 1
	if (tower_1_height % 2 == 0)
	{
		swap_disk(tower1, tower2);
	}
	else
	{
		swap_disk(tower1, tower3);
	}

	// Tower 2
	swap_disk(tower2, tower3);
	swap_disk(tower2, tower1);

	// Tower 3
	swap_disk(tower3, tower2);
	swap_disk(tower3, tower1);

	int tower_3_height = tower_height_recursive(tower3);

	if (tower_3_height == max_height)
	{
		return;
	}
	else
	{
		tower_of_hanoi_solver(tower1, tower2, tower3,  max_height);
	}


}

Why is the swap() function not updating the pointers in the tower_of_hanoi_solver() function - and hence the original pointers as well?

答案1

得分: 0

代码中有太多内容,我无法为您提供修复,但通常我认为问题在于您对将指针作为参数传递给函数时发生的情况有误解。

在像void swap_disk(disk* swap_tower_a, disk* swap_tower_b)这样的调用中,指针swap_tower_aswap_tower_b是按值传递的,这意味着在swap_disk内部,您可以访问传递的指针值的副本,而不是这些变量本身。所以,例如以下代码不是您想要的效果:

// ...
else if (swap_tower_a != NULL && swap_tower_b == NULL)
{
swap_tower_b = push(swap_tower_b, top_tower_a->value);
// ...
}

假设swap_tower_a不为空,swap_tower_b为空,然后push将返回一个新分配的disk,并将其分配给swap_tower_b,但swap_tower_b只是传递给swap_disk的指针变量的副本。将新值分配给其本地副本不会影响调用代码使用的变量。要实现这一点,您需要使swap_disk要么接受指向指针的指针,要么接受指向指针的引用——这取决于您,通常在C++中使用引用,但您编写的代码看起来非常像C,所以您可能更喜欢disk**

英文:

There is too much code there for me to give you a fix, but generally I think the problem is that you are misunderstanding what happens when you pass a pointer to a function as an argument.

In a call likevoid swap_disk(disk* swap_tower_a, disk* swap_tower_b) the pointers swap_tower_a and swap_tower_b are being passed by value, this means inside of swap_disk you have access to copies of the pointer values you passed in, not those variables themselves. So for example the following is not doing what you think it is doing:

// ...
else if (swap_tower_a != NULL &amp;&amp; swap_tower_b == NULL)
{
	swap_tower_b = push(swap_tower_b, top_tower_a-&gt;value);
	// ...
}

Say swap_tower_a is not null and swap_tower_b is null, then push is going to return a newly allocated disk and that is being assigned to swap_tower_b but swap_tower_b is just a copy of the pointer variable passed into swap_disk. Assigning a new value to a local copy of it will not affect the variable used by the calling code. To do that you would need swap_disk to either take pointers to pointers to disks or references to pointers to disks -- which is up to you, typically in C++ you use references, but you are writing very C-looking code so might prefer disk**.

huangapple
  • 本文由 发表于 2023年7月18日 14:56:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76710201.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定