1、概念
- 前序遍历:a、访问根节点 b、访问左节点 c、访问右节点
- 中序遍历:a、访问左节点 b、访问根节点 c、访问右节点
- 后序遍历:a、访问左节点 b、访问右节点 c、访问根节点
2、已知前序遍历、中序遍历还原二叉树
思想: 前序遍历的第一个元素是根结点,然后根据根结点在中序遍历中的位置将二叉树分成左子树和右子树,然后递归左右子树,继续上面的查找根结点,拆分左右子树,直至为nil
具体代码:
@interface TNode : NSObject
@property (nonatomic, assign) NSInteger value;
@property (nonatomic, strong) TNode *leftNode;
@property (nonatomic, strong) TNode *rightNode;
@end
@implementation TNode
@end
// 根据前序遍历和中序遍历获取二叉树
void getNodeWithPreAndMin(TNode **rootNode, NSArray *arrayPre, NSArray *arrayMin) {
if ((arrayPre.count == 0) && (arrayMin.count == 0)) {
return;
}
NSNumber *root = arrayPre.firstObject; // 获取根结点
TNode *node = [[TNode alloc] init];
*rootNode = node;
node.value = [root integerValue];
__block NSInteger rootIndex = 0; // 根结点在中序遍历中的位置
[arrayMin enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj integerValue] == [root integerValue]) {
rootIndex = idx;
*stop = YES;
}
}];
// 左树枝处理
NSArray *arrayLeftPre = [arrayPre subarrayWithRange:NSMakeRange(1, rootIndex)];
NSArray *arrayLeftMin = [arrayMin subarrayWithRange:NSMakeRange(0, rootIndex)];
TNode *leftNode = nil;
getNodeWithPreAndMin(&leftNode, arrayLeftPre, arrayLeftMin);
node.leftNode = leftNode;
// 右树枝处理
NSArray *arrayRightPre = [arrayPre subarrayWithRange:NSMakeRange(rootIndex + 1, arrayPre.count - rootIndex - 1)];
NSArray *arrayRightMin = [arrayMin subarrayWithRange:NSMakeRange(rootIndex + 1, arrayMin.count - rootIndex - 1)];
TNode *rightNode = nil;
getNodeWithPreAndMin(&rightNode, arrayRightPre, arrayRightMin);
node.rightNode = rightNode;
}
// 打印前序遍历
void printNodePre(TNode *node) {
if (node) {
NSLog(@"%ld", node.value);
printNodePre(node.leftNode);
printNodePre(node.rightNode);
}
}
// 打印中序遍历
void printNodeMin(TNode *node) {
if (node) {
printNodeMin(node.leftNode);
NSLog(@"%ld", node.value);
printNodeMin(node.rightNode);
}
}
// 打印后序遍历
void printNodeLater(TNode *node) {
if (node) {
printNodeLater(node.leftNode);
printNodeLater(node.rightNode);
NSLog(@"%ld", node.value);
}
}
例如:
NSArray *arrayPre = @[ @(1), @(2), @(4), @(7), @(3), @(5), @(6), @(8) ];
NSArray *arrayMin = @[ @(4), @(7), @(2), @(1), @(5), @(3), @(8), @(6) ];
TNode *rootNode = nil;
getNodeWithPreAndMin(&rootNode, arrayPre, arrayMin);
NSLog(@"前序遍历");
printNodePre(rootNode);
NSLog(@"中序遍历");
printNodeMin(rootNode);
NSLog(@"后序遍历");
printNodeLater(rootNode);
3、已知中序遍历、后序遍历还原二叉树
思想:同上,后序遍历的最后一个元素是根结点,然后根据根结点在中序遍历中的位置将二叉树分成左子树和右子树,然后递归左右子树,继续上面的查找根结点,拆分左右子树,直至为nil
具体代码:
// 根据中序遍历和后序遍历获取二叉树
void getNodeWithMinAndLater(TNode **rootNode, NSArray *arrayMin, NSArray *arrayLater) {
if ((arrayMin.count == 0) && (arrayLater.count == 0)) {
return;
}
NSNumber *root = arrayLater.lastObject; // 获取根结点
TNode *node = [[TNode alloc] init];
*rootNode = node;
node.value = [root integerValue];
__block NSInteger rootIndex = 0; // 根结点在中序遍历中的位置
[arrayMin enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj integerValue] == [root integerValue]) {
rootIndex = idx;
*stop = YES;
}
}];
// 左树枝处理
NSArray *arrayLeftMin = [arrayMin subarrayWithRange:NSMakeRange(0, rootIndex)];
NSArray *arrayLeftLater = [arrayLater subarrayWithRange:NSMakeRange(0, rootIndex)];
TNode *leftNode = nil;
getNodeWithMinAndLater(&leftNode, arrayLeftMin, arrayLeftLater);
node.leftNode = leftNode;
// 右树枝处理
NSArray *arrayRightMin = [arrayMin subarrayWithRange:NSMakeRange(rootIndex + 1, arrayMin.count - rootIndex - 1)];
NSArray *arrayRightLater = [arrayLater subarrayWithRange:NSMakeRange(rootIndex, arrayLater.count - rootIndex - 1)];
TNode *rightNode = nil;
getNodeWithMinAndLater(&rightNode, arrayRightMin, arrayRightLater);
node.rightNode = rightNode;
}
注:只有前序遍历和后序遍历无法确定二叉树。