c语言 树遍历算法,Morris 二叉树遍历算法(C语言描述)

本文介绍了Morris二叉树遍历算法,包括前序、中序和后序遍历。这种算法的时间复杂度为O(n),空间复杂度为O(1)。Morris中序遍历通过修改树结构进行遍历,当当前节点的左子节点为空时访问节点,否则找到左子树中最右侧节点,将其指向当前节点,然后访问当前节点。前序遍历类似,只是访问节点的时机不同。后序遍历则需要额外的辅助节点。详细算法实现代码已给出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于二叉树的遍历,在数据结构中介绍有三种遍历方式:前序遍历,中序遍历和后序遍历. 这三种遍历方式通常采用递归或者迭代方式实现.

递归实现或者迭代实现都是时间复杂度为O(n)的算法,并且在遍历过程中需要用到堆栈保存信息,它们的空间复杂度也都是O(n).

下面要介绍的Morris二叉树遍历算法是时间复杂度为O(n),空间复杂度为O(1)的遍历算法,它也有前序遍历,中序遍历和后续遍历三种遍历顺序

Morris 中序遍历算法

算法的简要概述如下:

指定cur指针 初始指向 root节点

1.当cur指针的左子节点为NULL时,说明在其左子树内没有前驱节点,访问cur指针中的元素,cur指针指向cur指针的右节点.

2.当cur指针的左子节点不为NULL时,用指针指向cur左子树的最右节点

2.1当最右节点的右节点为NULL时,将其指向cur,cur指向cur的左节点

2.2当最右节点的右节点不为NULL时,将其置NULL,访问cur指针中元素,cur指向cur的右节点.

重复 1 , 2步骤,直到cur指针为NULL

算法执行步骤如图所示

959247c29a7b

morris 中序遍历

算法实现:

struct TreeNode {

int val;

struct TreeNode *left;

struct TreeNode *right;

};

void Morris_LDR(struct TreeNode* root) {

struct TreeNode *cur = root;

while (cur != NULL) {

if (cur->left == NULL) {

printf("now :%d \n",cur->val);

cur = cur->right;

} else {

struct TreeNode *temp = cur->left;

while (temp->right != NULL && temp->right != cur) {

temp = temp->right;

}

if (temp->right == NULL) {

temp->right = cur;

cur = cur->left;

} else {

temp->right = NULL;

printf("now :%d \n",cur->val);

cur = cur->right;

}

}

}

}

Morris 前序遍历算法

与递归算法相似,Morris 前序遍历与 Morris中序遍历算法在骨架上一致,只是调整了输出数据的位置.

算法描述

指定cur指针 初始指向 root节点

1.当cur指针的左子节点为NULL时,说明在其左子树内没有前驱节点,访问cur指针中的元素,cur指针指向cur指针的右节点.

2.当cur指针的左子节点不为NULL时,用指针指向cur左子树的最右节点

2.1当最右节点的右节点为NULL时,将其指向cur,访问cur指针中元素,cur指向cur的左节点

2.2当最右节点的右节点不为NULL时,将其置NULL,cur指向cur的右节点.

重复 1 , 2步骤,直到cur指针为NULL

算法执行图示

959247c29a7b

mirros 前序遍历

算法实现:

struct TreeNode {

int val;

struct TreeNode *left;

struct TreeNode *right;

};

void Morris_DLR(struct TreeNode* root) {

struct TreeNode *cur = root;

while (cur != NULL) {

if (cur->left == NULL) {

printf("now :%d \n",cur->val);

cur = cur->right;

} else {

struct TreeNode *temp = cur->left;

while (temp->right != NULL && temp->right != cur) {

temp = temp->right;

}

if (temp->right == NULL) {

temp->right = cur;

printf("-now :%d \n",cur->val);

cur = cur->left;

} else {

temp->right = NULL;

cur = cur->right;

}

}

}

}

Mirros 后序遍历

Mirros 后序遍历比较麻烦,需要创建额外的根节点辅助遍历过程,还要有一个过程来倒序访问元素.

算法描述

创建head节点,使head节点是head节点的左节点指向root节点.

创建 cur指针,使cur指针指向head节点.

1.当cur指针的左节点为NULL时,使cur指针指向cur指针的右节点.

2.当cur指针的左节点不为NULL时,找到cur指针的左节点的最右节点(中序遍历时的前驱节点).

2.1当最右节点的右节点为NULL时,使最右节点的右节点指向cur指针,

使cur指针指向cur指针的左子节点.

2.2 当最右节点的右节点不为NULL时,使最右节点的右节点指向NULL, 并倒叙访问从cur指针的左节点到最右节点的所有子节点,使cur指针指向cur指针的右子节点.

重复1 , 2过程,直到 cur指针指向NULL.

算法执行图示(图中的虚线框表示辅助的头结点)

959247c29a7b

mirros 后序遍历

算法实现

struct TreeNode {

int val;

struct TreeNode *left;

struct TreeNode *right;

};

void Morris_LRD(struct TreeNode *root) {

struct TreeNode *head = (struct TreeNode *)calloc(1, sizeof(struct TreeNode));

struct TreeNode *cur = head;

head->left = root;

while (cur != NULL) {

if (cur -> left == NULL) {

cur = cur -> right;

} else {

struct TreeNode *temp = cur -> left;

while (temp->right != NULL && temp-> right != cur) {

temp = temp -> right;

}

if (temp -> right == NULL){

temp -> right = cur;

cur = cur -> left;

} else { // (temp -> right == cur

temp -> right = NULL;

struct TreeNode *index = cur->left;

printf("reverse ( ");

while (index != NULL) {

printf("%d ",index->val);

index = index->right;

}

printf(" )\n");

cur = cur -> right;

}

}

}

head->left = NULL;

free(head);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值