1. 程式人生 > >使用棧非遞迴實現複製二叉樹

使用棧非遞迴實現複製二叉樹

#include "iostream"
using namespace std;
#define max 20  //the number of node
typedef struct BTNode
{
	char data;
	struct BTNode *lc,*rc;
}BTree;

#define STACK_INIT_SIZE 100
#define STACK_INCR 10

typedef struct 
{ 
	BTree *base;
	BTree *top;
	int stackSize;
} Stack;

void initStack(Stack &stack)   //初始化棧
{ 
	stack.base = stack.top = (BTree *)malloc(sizeof(BTree) * STACK_INIT_SIZE);
	stack.stackSize = STACK_INIT_SIZE;
}

void pop(Stack &S, BTree * &T)  //出棧
{
	if(S.top == S.base) 
	{
		T = NULL;
		return ;
	}
	T = --S.top;
}

void push(Stack &S, BTree * &T)   //進棧
{
	if(S.top - S.base >= S.stackSize) 
	{
		S.base=(BTree*)realloc(S.base,(S.stackSize+STACK_INCR)*sizeof(BTree));
		S.top = S.base + S.stackSize;
		S.stackSize += STACK_INCR;
	}
	*S.top++ = *T;
}

bool stackEmpty(Stack S)   //判斷棧是否為空
{
	return S.top == S.base ? true : false;
}

BTree *createtree(char *str,int i,int m)  //建立樹
{
	BTree *p;
	if(i >= m)
		return 0;
	p = (BTree*)malloc(sizeof(BTree));
	p->data = str[i];
	p->lc = createtree(str,2*i+1,m);
	p->rc = createtree(str,2*i+2,m);
	return (p);
}

void PreOrder(BTree *t)  //樹的先序遍歷
{
	if(t != NULL)
	{
		cout<<t->data;
		if(t->lc)
		{
			cout<<"->";
			PreOrder(t->lc);
		}
		if(t->rc)
		{
			cout<<"->";
			PreOrder(t->rc);
		}
	}
}

void BiTreeCopy_Stack(BTree *root, BTree * ©root) //非遞迴複製二叉樹,將root複製到copyroot
{ 
	/*指標與引用的區別
	指標:存放變數地址的一個變數,邏輯上是獨立的,它可以被改變。
	引用:是一個別名,邏輯上不是獨立的,它的存在具有依附性,必須在一開始就被初始化,且"從一而終"
	*/
	Stack S1, S2;
	initStack(S1); //初始化棧
	initStack(S2);

	BTree *p = root;
	BTree *q, *pre;  //q用來每次建立新結點; pre為臨時根結點

	copyroot = pre = (BTree*)malloc(sizeof(BTree));

	while(p||!stackEmpty(S1)) //如果當前結點有左孩子,則一直向左走
	{
		while(p) 
		{ 
			q = (BTree*)malloc(sizeof(BTree));
			q->data = p->data;
			q->lc = q->rc = NULL;
			pre->lc = q;
			pre = q;
			push(S1, p);
			push(S2, q);
			p = p->lc;
		}

		pop(S1, p); //指標移到棧中最後一個元素
		pop(S2, q);

		while(!p->rc && !stackEmpty(S1))  //如果當前結點的右孩子為空,則棧中存放的左孩子全部出棧
		{
			pop(S1, p); 
			pop(S2, q);
		}

		p = p->rc; //p指向root中第一個有右孩子的結點
		q = q->rc;

		if(p) //對右子樹進行操作
		{
			q = (BTree*)malloc(sizeof(BTree));
			q->data = p->data;
			q->lc = q->rc = NULL;
			pre->rc = q;
			pre = q;
			push(S1, p);
			push(S2, q);
			p = p->lc;
		}
	}
	pre = copyroot; //使臨時根結點重新指回根結點
	copyroot = copyroot->lc;
	free(pre);   //釋放指臨時根結點
}

int main()
{
	int i,n;
	char str[max];
	BTree *root,*copyroot;

	cout<<"please input the number of node:";
	cin>>n;
	cout<<endl;

	cout<<"please input "<<n<<" nodes:";
	for(i = 0;i < n;i++)
		cin>>str[i];

	root = createtree(str,0,n); 
	cout<<"the PreOrder:";
	PreOrder(root);
	cout<<endl;

	BiTreeCopy_Stack(root, copyroot);
	cout<<"after the copy the PreOrder:";
	PreOrder(copyroot);
	cout<<endl;

	system("pause");
	return 0;
}


相關推薦

使用實現複製

#include "iostream" using namespace std; #define max 20 //the number of node typedef struct BTNode { char data; struct BTNode *lc,*rc;

實現計算葉子節點的個數

#include<stdio.h> #include<stdlib.h> #include <malloc.h> #include <stack> #define MAXSIZE 50 typedef struct Bin

【資料結構週週練】013 利用演算法求的高

一、前言 二叉樹的高是樹比較重要的一個概念,指的是樹中結點的最大層數本次演算法通過非遞迴演算法來求得樹的高度,借用棧來實現樹中結點的儲存。 學英語真的很重要,所以文中的註釋還有輸出以後會盡量用英語寫,文中出現的英語語法或者單詞使用錯誤,還希望各位英語大神能不吝賜教。 二、題目 將

資料結構--遍歷(利用輔助

#include "StdAfx.h" #include <stdio.h> #include <stdlib.h> /*非遞迴方法前序遍歷二叉樹,利用輔助棧(指標陣列實現)。由於對指標不是很熟悉,程式碼較為混亂,基本上實現遍歷的功能。

演算法算的高度

1.方法思路:用深搜和後序遍歷結合,遍歷所有節點,記錄最大高度。時間為O(n),空間為O(max)。(自創) 程式碼如下(未測試): 1 2 3 4 5 6 7 8 9 10 11

JAVA 先序、中序、後序、層序,遍歷

定義一個二叉樹 package com.niuke.binaryTree; public class binaryTree { int data; binaryTree left; binaryTree right; public binaryTree(int

先序、層次建立並用三序遍歷之(C語言)

 先序就是直接用遞迴的方法建立,層次使用了輔助陣列,後一種方法我覺得友好多了。 #include "stdio.h" #define MAXSIZE 50 #define TRUE 1 #define FALSE 0 typedef int boo

求取的最大/小深度

分層遍歷的思路:二叉樹分層遍歷用到的是BFS(廣度優先搜尋),顯然這必須維護一個佇列。但是一個佇列只能得到遍歷結果,並不能一層一層分開,所以必須使用兩個佇列curr和next,curr儲存當前層的所有結點指標,next儲存下一層的結點指標,遍歷的過程就是出佇列的過程,在對c

資料結構(四)之遍歷

void Inoder(Bitree root)//二叉樹的中序遍歷非遞迴 { IniStack(&S);//初始化一個棧 p=root; while(!isEmpty(S)||p!=NULL) { if(p!=NULL)//如果當前結點不為空進棧 { pu

後序遍歷

非遞迴後序遍歷演算法思想   後序遍歷的非遞迴演算法中節點的進棧次數是兩個,即每個節點都要進棧兩次,第二次退棧的時候才訪問節點。   第一次進棧時,在遍歷左子樹的過程中將”根”節點進棧,待左子樹訪問完後,回溯的節點退棧,即退出這個”根”節點,但不能立即訪

C++建立、遍歷的基本操作

       最近學了二叉樹,這個資料結構和它的名字一樣,真是二叉。如果單純的讓我想這樣的演算法,以筆者的腦子想一輩子都想不出來。二叉樹剛學完,老師又講了圖。        俗話說,不能在一棵樹上吊死,那我選擇在二叉樹上吊死。關鍵是圖還在下面扯著你,二叉樹這個資料結構不會

JAVA遍歷

不錯 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild

java 實現平衡

bsp get 實現 urn ole lean left current this public class 平衡二叉樹{ public class TreeNode { TreeNode left; TreeNode right;

遍歷--C語言

  之前寫了關於二叉樹的非遞迴遍歷演算法的程式碼,今天把二叉樹的遞迴遍歷演算法的程式碼補上,內容很簡單!但是今天也算是寫了一會兒程式碼了~姑且這麼認為吧~ 程式碼: #include <stdio.h> #include <stdlib.h> typedef

遍歷 求高度 和 節點數 和 葉子節點數

1,二叉樹的儲存結構: typedef struct Node { char data; struct Node *lchild,*rchild; }Node,*BiTree;2, 建

C語言構造並遍歷

#include<stdio.h> #include<malloc.h> #define FALSE 1 #define ERROR 0 #define OK 1 #define ON 0 typedef struct BiTNode {

方法對進行層次遍歷

      在這裡看到了這個題。層次遍歷是用佇列,一級一級地入佇列然後輸出。而用遞迴的話,我首先想到是用兩個棧來模擬佇列,在遞迴遍歷二叉樹的過程中入棧,然後最後一次性出棧。但仔細思考後發現無法做到層次遍歷。在這裡看到了正確的方法。      主要程式碼如下: 1 void PrintNodeAtLev

歸遍歷

ack val {} || 遍歷 result args str sys public class Solution { public static void main(String[] args) {} public List<I

實現

二叉樹非遞迴實現會比較難理解一點,不過只要理解了非遞迴的,那麼遞迴的就非常好理解了。接下來進行圖文詳解。 C程式碼下載 C++程式碼下載 java程式碼下載 ( 備用地址下載) 導航 1.建立二叉樹 2.前序遍歷二叉樹 3.中序遍歷二叉樹 4.後序遍歷二叉

後序遍歷實現(java)

後序遍歷:雙棧法,和層次遍歷(雙佇列)很相似,唯一區別在於層次遍歷用的 是佇列,後序遍歷用的是棧。 public static void posOrderUnRecur1(Node head){ System.out.print("PosOrder:"); if(head !=