Morris 算法遍历二叉树

Morris 就是大家所知的KMP算法中的M。

一、Morris 算法遍历的大概流程如下:

定义一个节点Cur 指向当前节点。

1、如果Cur节点无左子树,则将Cur节点向右移动。

2、如果Cur节点有左子树,找到左子树上最右节点,mostright

(1)mostright的右孩子为空,则将mostright的右孩子的指针指向Cur。然后Cur向左移动

(2)如果mostright已经指向Cur,则将mostright指向空,Cur向右移动

二、代码如下:

struct	Node {
	int value;
	Node right;
	Node left;
	Node(int data) :value(data), right(NULL), left(NULL) {}
};
void Morris (Node *Head)
{
        if (root == null)
	{
	    return;
	}
	Node Cur1 = Head;
	Node Cur2 = NULL;
	while (Cur1 != NULL)
	{
	    Cur2 = Cur1.left;
	    if (Cur2 != NULL)   
	    {
		while (Cur2.right != NULL && Cur2->right != Cur1)
		    Cur2 = Cur2.rght;
		if (Cur2.right == NULL)
		{
		    Cur2.right = Cur1;
	            Cur1 = Cur1.left;
	            continue;
	        }
		else
		    Cur2.right = NULL;
		}
		Cur1 = Cur1.right;
	}
}

三、Morris 前续遍历:

void MorrisPre(Node *Head)
{
	if (Head == null)
	{
		return;
	}
	Node Cur1 = root;
	Node Cur2 = NULL;
	while (Cur1 != NULL)
	{
		Cur2 = Cur1.left;
		if (Cur2 != NULL)
		{
			while (Cur2.right != NULL && Cur2.right != Cur1)
			{
				Cur2 = Cur2.rght;
			}
			if (Cur2.right == NULL)
			{
				Cur2.right = Cur1;
				cout << Cur1.value << "\t"; //第一次到达就打印
				Cur1 = Cur1.left;
				continue;
			}
			else
			{
				Cur2.right = NULL;
			}
		}else
			cout << Cur1.value << "\t";    //左子树不存在直接打印
		Cur1 = Cur1.right;
	}
}

四、Morris 中续遍历:

void MorrisIn(Node *Head)
{
	if (root == null)
	{
		return;
	}
	Node Cur1 = Head;
	Node Cur2 = NULL;
	while (Cur1 != NULL)
	{
		Cur2 = Cur1.left;
		if (Cur2 != NULL)
		{
			while (Cur2.right != NULL && Cur2.right != Cur1)
			{
				Cur2 = Cur2.rght;
			}
			if (Cur2.right == NULL)
			{
				Cur2.right = Cur1;
				Cur1 = Cur1.left;
				continue;
			}
			else
			{
				Cur2.right = NULL;
			}
		}
		cout << Cur1.value << "\t";    //如果没有左子树,则打印当前节点,如果有左子树,第二次来到该节点的时候打印当前节点,统一一下就是,如果该节点向右移动,就打印该节点。
		Cur1 = Cur1.right;
	}
}

五、Morris 后续遍历:

后续遍历就是将遍历到第二次的节点逆序打印该节点左子树右边界。

void MorrisPos(Node *Root)
{
	if (Root == null)
	{
		return;
	}
	Node Cur1 = Root;
	Node Cur2 = NULL;
	while (Cur1 != NULL)
	{
		Cur2 = Cur1.left;
		if (Cur2 != NULL)
		{
			while (Cur2.right != NULL && Cur2.right != Cur1)
			{
				Cur2 = Cur2.rght;
			}
			if (Cur2.right == NULL)
			{
				Cur2.right = Cur1;
				Cur1 = Cur1.left;
				continue;
			}
			else
			{
				Cur2.right = NULL;
				printEdge(Cur1.left);  //
			}
		}
		Cur1 = Cur1.right;
	}
	printEdge(Head); //
}
//后续遍历的打印
void printEdge(Node head)
{
	Node Tail = reverseEdge(head);
	Node Cur = Tail;
	while (Cur != NULL)
	{
		cout << Cur.value << "\t";
		Cur = Cur.right;
	}
	reverseEdge(head);
}
//反转右边界,和链表的反转差不多
Node reverseEdge(Node From)
{
	Node Pre = NULL;
	Node Next = NULL;
	while (From != NULL)
	{
		Next = From.right;
		From.right = Pre;
		Pre = From;
		From = Next;
	}
	return Pre;
}

你可能感兴趣的:(算法,Morris,算法遍历)