1. 程式人生 > >C++作業:將左右孩子互換 / 複製一棵二叉樹

C++作業:將左右孩子互換 / 複製一棵二叉樹

/* 邵發, 1309班,  */

/*
12周作業

練習1:編寫遞迴演算法、將左右孩子互換 (用遞迴)
練習2:編寫複製一棵二叉樹 (不用遞迴)

*/

#include <stdio.h>

// 定義節點
struct Node
{
	int value;
	Node* left, *right;
};

// 練習1:交換左右孩子節點
void SwapChildren(Node* tree)
{
	if(!tree) return;
	
	Node* t = tree->left;
	tree->left = tree->right;
	tree->right = t;

	SwapChildren(tree->left);
	SwapChildren(tree->right);
}

// 練習2:複製一棵二叉樹

// 遞迴版本
// 也可以把引用改成**,不過可讀性會差一些
void Copy_r(Node* oldtree, Node* &newtree)
{
	// 空節點
	if(oldtree == NULL)
	{
		newtree = NULL;
	}
	else
	{
		// 附加節點
		newtree = new Node();
		// 拷貝節點的值
		newtree->value = oldtree->value;

		// 遞迴拷貝子節點
		Copy_r(oldtree->left, newtree->left);
		Copy_r(oldtree->right,newtree->right);
	}
}

// 非遞迴版本 (直接由遞迴版本改造, 由自定義棧替換遞迴邏輯)
void Copy_nr(Node* oldtree, Node** newtree)
{
	Node*  stack_old[256];
	Node** stack_new[256];  // 注意這裡存放的是**
	int top = 0; // 頂點位置,同時也是棧的元素個數

	// 推入根節點
	stack_old[top] = oldtree;
	stack_new[top] = newtree;
	top ++;

	while(top > 0)
	{
		// 取節點複製
		top--; // 先減再取
		Node** pNew = stack_new[top];
		Node*  pOld = stack_old[top];
		//top --;

		// 複製, 跟前面copy_r實際上相同
		// 使用引用來去掉一個*,否則可讀性欠佳
		Node*& p = *pNew;
		if(pOld == NULL)
		{
			p = NULL;
		}
		else
		{
			// 複製本節點
			p = new Node();
			p->value = pOld->value;

			// 再複製子節點, 相當於遞迴呼叫
			stack_new[top] = & (p->left);
			stack_old[top] = pOld->left;
			top ++;

			stack_new[top] = & (p->right);
			stack_old[top] = pOld->right;
			top ++;
		}
	}
}