生成二叉树
首先得快速生成一棵二叉树
才能继续接下来的工作,下面是一棵二叉排序树
的生成
定义树和树结点的结构体
1 2 3 4 5 6 7 8 9
| typedef int ElemType;
typedef struct Node { ElemType data; struct Node* left; struct Node* right; } Node, *SortTree;
|
向二叉排序树中插入结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
void insert(SortTree *tree, ElemType elemType) { if ((*tree) == NULL) { (*tree) = (Node*)malloc(sizeof(Node)); (*tree)->data = elemType; (*tree)->right = NULL; (*tree)->left = NULL; } else if (elemType < (*tree)->data) { insert(&((*tree)->left), elemType); } else { insert(&((*tree)->right), elemType); } }
|
通过如下代码,向二叉树中插入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| SortTree sortTree = NULL;
insert(&sortTree, 5); insert(&sortTree, 3); insert(&sortTree, 7); insert(&sortTree, 2); insert(&sortTree, 4); insert(&sortTree, 6); insert(&sortTree, 8);
|
访问结点数据
1 2 3 4 5 6 7
|
void visit(ElemType elemType) { printf("%d ", elemType); }
|
遍历二叉树
递归遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
void inorderTraversal(SortTree tree) { if (tree != NULL) { inorderTraversal(tree->left); visit(tree->data); inorderTraversal(tree->right); } }
void preorderTraversal(SortTree tree) { if (tree != NULL) { visit(tree->data); preorderTraversal(tree->left); preorderTraversal(tree->right); } }
void postorderTraversal(SortTree tree) { if (tree != NULL) { postorderTraversal(tree->left); postorderTraversal(tree->right); visit(tree->data); } }
|
非递归遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
void inorderTraversal2(SortTree tree) { int top = -1; Node* stack[STACK_MAX_LENGTH];
SortTree p = tree;
while (p != NULL || top != -1) { if (p != NULL) { stack[++top] = p; p = p->left; } else { p = stack[top--]; visit(p->data);
p = p->right; } } }
void preorderTraversal2(SortTree tree) { int top = -1; Node* stack[STACK_MAX_LENGTH];
SortTree p = tree;
while (p != NULL || top != -1) { if (p != NULL) { stack[++top] = p;
visit(p->data);
p = p->left; } else { p = stack[top--];
p = p->right; } } }
void postorderTraversal2(SortTree tree) { int top = -1; Node* stack[STACK_MAX_LENGTH];
SortTree p = tree; Node *t = NULL;
while (p != NULL || top != -1) { if (p != NULL) { stack[++top] = p; p = p->left; } else { p = stack[top]; if (p->right != NULL && p->right != t) { p = p->right; } else { p = stack[top--]; visit(p->data);
t = p; p = NULL; } } } }
|
层序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
void levelTraversal(SortTree tree) { Node *queue[QUEUE_MAX_LENGTH]; int front = 0, rear = 0;
SortTree p = tree;
queue[rear++] = p;
while (rear > front){ p = queue[front++]; visit(p->data); if (p->left != NULL) queue[rear++] = p->left; if (p->right != NULL) queue[rear++] = p->right; } }
|
线索二叉树
中序线索二叉树
添加ltag
rtag
标志结点的左右指针是否是线索
定义线索二叉树结点的结构体
1 2 3 4 5 6
| typedef struct Node { ElemType data; struct Node *left, *right; int ltag, rtag; } Node, *SortTree;
|
在插入结点时,将ltag
rtag
初始化为0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
void insert(SortTree *tree, ElemType elemType) { if ((*tree) == NULL) { (*tree) = (Node*)malloc(sizeof(Node)); (*tree)->data = elemType; (*tree)->right = NULL; (*tree)->left = NULL; (*tree)->rtag = 0; (*tree)->ltag = 0; } else if (elemType < (*tree)->data) { insert(&((*tree)->left), elemType); } else { insert(&((*tree)->right), elemType); } }
|
通过中序遍历给二叉树线索化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
void inThread(Node *currentNode, Node **previousNode) { if (currentNode == NULL) return;
inThread(currentNode->left, previousNode);
if ((*previousNode) != NULL && (*previousNode)->right == NULL) { (*previousNode)->rtag = 1; (*previousNode)->right = currentNode; } if (currentNode->left == NULL) { currentNode->ltag = 1; currentNode->left = (*previousNode); } (*previousNode) = currentNode;
inThread(currentNode->right, previousNode); }
void createInThread(SortTree sortTree) { if (sortTree == NULL) return;
Node *preNode = NULL; inThread(sortTree, &preNode); preNode->right = NULL; preNode->rtag = 1; }
|
在中序线索二叉树中,寻找某结点的前驱结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
Node* firstNode(SortTree sortTree) { Node *temp = sortTree; while (temp->ltag == 0) temp = temp->left;
return temp; }
Node* nextNode(Node *node) { if (node->rtag == 0) return firstNode(node->right);
return node->right; }
|
在中序线索二叉树中,寻找某结点的后继结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
Node* tailNode(SortTree sortTree) { Node *temp = sortTree; while (temp->rtag == 0) temp = temp->right;
return temp; }
Node* preNode(Node *node) { if (node->ltag == 0) return tailNode(node->left);
return node->left; }
|
遍历中序线索二叉树
1 2 3 4 5 6 7 8 9 10 11
|
void inOrder(SortTree sortTree) { Node *node = firstNode(sortTree); while (node != NULL) { visit(node->data); node = nextNode(node); } }
|
先序线索二叉树
在先序线索二叉树中,若某结点拥有左子树,那么就无法通过左线索来寻找前驱,此时他的前驱有可能是父结点,也有可能是以左兄弟结点为根结点的子树的最后一个结点,无论如何要访问其父结点,所以在结点的结构中添加父结点,形成三叉树
定义线索三叉树结点的结构体
1 2 3 4 5 6 7
| typedef struct Node { ElemType data; struct Node *left, *right; struct Node *parent; int ltag, rtag; } Node, *SortTree;
|
插入结点,在插入结点时,需指明结点的父结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| SortTree parentNode = NULL;
void insert(SortTree *tree, ElemType elemType) { if ((*tree) == NULL) { (*tree) = (Node*)malloc(sizeof(Node)); (*tree)->data = elemType; (*tree)->right = NULL; (*tree)->left = NULL; (*tree)->parent = parentNode; (*tree)->rtag = 0; (*tree)->ltag = 0; parentNode = NULL; } else if (elemType < (*tree)->data) { parentNode = *tree; insert(&((*tree)->left), elemType); } else { parentNode = *tree; insert(&((*tree)->right), elemType); } }
|
通过先序遍历给三叉树线索化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
void preThread(Node *currentNode, Node **previousNode) { if (currentNode == NULL) return;
if ((*previousNode) != NULL && (*previousNode)->right == NULL) { (*previousNode)->rtag = 1; (*previousNode)->right = currentNode; } if (currentNode->left == NULL) { currentNode->ltag = 1; currentNode->left = (*previousNode); } (*previousNode) = currentNode;
if (currentNode->ltag == 0) preThread(currentNode->left, previousNode);
preThread(currentNode->right, previousNode); }
void createPreThread(SortTree sortTree) { if (sortTree == NULL) return;
Node *preNode = NULL; preThread(sortTree, &preNode); preNode->right = NULL; preNode->rtag = 1; }
|
在先序线索三叉树中,寻找某结点的前驱结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
Node* tailNode(SortTree sortTree) { if (sortTree->rtag == 0) return tailNode(sortTree->right); else if (sortTree->ltag == 0) return tailNode(sortTree->left);
return sortTree; }
Node* preNode(Node *node) { if (node->ltag == 1) return node->left;
if (node->parent != NULL && node->parent->left != node) return tailNode(node->parent->left); else return node->parent; }
|
在先序线索三叉树中,寻找某结点的后继结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
Node* nextNode(Node *node) { if (node->ltag == 0) return node->left;
return node->right; }
|
遍历先序线索三叉树
1 2 3 4 5 6 7 8 9 10 11
|
void preOrder(SortTree sortTree) { Node *node = sortTree; while (node != NULL) { visit(node->data); node = nextNode(node); } }
|
后序线索二叉树
在后序线索二叉树中,同样需要三叉树,因为如果某结点拥有右子树,那么就无法通过右线索来寻找后继,此时他的后继有可能是父结点,也有可能是以右兄弟结点为根结点的子树的第一个结点,无论如何要访问其父结点
通过先序遍历给三叉树线索化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
void postThread(Node *currentNode, Node **previousNode) { if (currentNode == NULL) return;
postThread(currentNode->left, previousNode);
postThread(currentNode->right, previousNode);
if ((*previousNode) != NULL && (*previousNode)->right == NULL) { (*previousNode)->rtag = 1; (*previousNode)->right = currentNode; } if (currentNode->left == NULL) { currentNode->ltag = 1; currentNode->left = (*previousNode); } (*previousNode) = currentNode; }
void createPostThread(SortTree sortTree) { if (sortTree == NULL) return;
Node *preNode = NULL; postThread(sortTree, &preNode);
if (preNode->right == NULL) preNode->rtag = 1; }
|
在先序线索三叉树中,寻找某结点的前驱结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
Node* preNode(Node *node) { if (node->rtag == 0) return node->right;
return node->left; }
|
在先序线索三叉树中,寻找某结点的后继结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
Node* firstNode(SortTree sortTree) { if (sortTree != NULL && sortTree->ltag == 0) return firstNode(sortTree->left);
if (sortTree != NULL && sortTree->rtag == 0) return firstNode(sortTree->right);
return sortTree; }
Node* nextNode(Node *node) { if (node->rtag == 1) return node->right;
if (node->parent != NULL && node->parent->right != node) return firstNode(node->parent->right);
return node->parent; }
|
遍历后序线索三叉树
1 2 3 4 5 6 7 8 9 10 11
|
void postOrder(SortTree sortTree) { Node *node = firstNode(sortTree); while (node != NULL) { visit(node->data); node = nextNode(node); } }
|