1. 程式人生 > >《資料結構》嚴蔚敏 用棧實現遞迴來解決hanoi問題

《資料結構》嚴蔚敏 用棧實現遞迴來解決hanoi問題

感覺書上對遞迴操作的棧理解的挺好的,有需要的可以去找一下書看一下

//hanoi problem

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

int times = 1;

void
move(char from,int n,char to)
{
	printf("%d times: Move disk %d from %c -> %c \n",times++,n,from,to);
}

int
hanoi(int n,char x,char y,char z)
{
	
	if(n == 1)
	{
		move(x,1,z);
	}
	else
	{
		hanoi(n-1,x,z,y);
		move(x,n,z);
		hanoi(n-1,y,x,z);
	}
	return times;
}

int main(int argc, char const *argv[])
{
	int times ;
	int n ;
	char x = 'X',y = 'Y',z = 'Z';

	printf("please enter the hanoi blocks: ");
	while(scanf("%d",&n) == 1)
	{
		times = hanoi(n,x,y,z);
		printf("all move %d times\n",times-1);
	}
	

	return 0;
}

非遞迴演算法,即自己構建這麼一個進棧入棧的過程,不過
用Visual Studio除錯的結果,在移動同樣多的盤子情況下,兩種方法消耗的記憶體相差不大,但時間有較大差別,使用迭代的方法花費的時間是遞迴方法的近十倍。原因有以下幾點:

迭代過程中要反覆地動態建立變數,這也是時間開銷差距的主要原因
遞迴過程由於編譯過程對遞迴變數和遞迴函式有很好的優化處理,因而效率較高

迭代程式碼

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

typedef struct record //用於記錄遞迴環境,放入棧中
{
	int n;
	char moveFrom;
	char moveTo;
	char swap;
	struct record *next;
} record;
typedef struct stack //定義一個棧
{
	record * records;
	int num;

} stack;
void push(record *record, stack *stack) //向棧內放置元素
{
	stack->num++;
	record->next = stack->records;
	stack->records = record;
}
record * pop(stack *stack) //從棧頂彈出元素
{
	record *record;
	stack->num--;
	record = stack->records;
	stack->records = stack->records->next;
	return record;
}

//move方法,實現將n個盤子從moveFrom柱藉助swap柱移動到moveTo柱
void move(int n, char moveFrom, char moveTo, char swap)
{
	stack stack = { NULL, 0 };
	record *record1, *p_record;
	//初始化棧
	record1 = (record *)malloc(sizeof(record));
	record1->n = n, record1->moveFrom = moveFrom, record1->moveTo = moveTo;
	record1->swap = swap;
	push(record1, &stack);
	//迭代開始
	while (stack.num != 0)
	{
		//從棧中取出元素,並進行相應操作
		p_record = pop(&stack);
		if (p_record->n == 1)
		{
			printf("%c->%c\t", p_record->moveFrom, p_record->moveTo);
			free(p_record);
			continue;
		}
//記錄遞迴環境,並放入棧中
		record *record2 = (record *)malloc(sizeof(record));
		record *record3 = (record *)malloc(sizeof(record));
		record *record4 = (record *)malloc(sizeof(record));
		record2->n = p_record->n - 1, record2->moveFrom = p_record->moveFrom,
			record2->moveTo = p_record->swap, record2->swap = p_record->moveTo;
		record3->n = 1, record3->moveFrom = p_record->moveFrom,
			record3->moveTo = p_record->moveTo, record3->swap = p_record->swap;
		record4->n = p_record->n - 1, record4->moveFrom = p_record->swap,
			record4->moveTo = p_record->moveTo, record4->swap = p_record->moveFrom;
		push(record4, &stack);
		push(record3, &stack);
		push(record2, &stack);

		//不要忘記釋放記憶體
		free(p_record);
	}
}
int main()
{
	int n = 3;
	//呼叫move方法
	move(n, 'A', 'B', 'C');
	
	return 0;
}