树和二叉树
1 树
树的节点的子节点可以有多个。是n个节点的有限集。
树的集合便是森林。
2 二叉树
二叉树是另一种树型结构。特点是每个i二点之多右两颗子树,并且二叉树的子树有左右之分,次序不能任意颠倒。
相关特征:
1 在二叉树的第i层之多有2的(i-1)次方(i>=1)
2 深度为k的二叉树之多有2的k次方减1。(等比数列)
3 对于任意的二叉树,叶子节点是n0,度为2的节点树为n2,则n0=n2+1.
假设度为1的节点数位n1。则总结点数可以表示为: n=n1+n0+n2.。 同时利用分支 n=n1+2*n2+1,两式联立得出结论。
4 具有n个节点的二叉树的深度位ceil(log(n)) +1。
3 二叉树的遍历:
二叉树的遍历有先序遍历,中序遍历,后序遍历。
先序遍历:先访问根节点,之后左子树,最后才是右子树。
中序遍历:先访问左子树,之后根节点,最后才是右子树。
后序遍历:先访问左子树,之后右子树,最后才是根节点。
//串的定长存储表示 #define MAX_NODE 50 #define ERROR 0 #define OK 1 typedef int Status #define MAX_ROW 100 #define MAX_SIZE 101 #define NULLKY '?' typedef int elemtype; typdef struct BTNode { char data; struct BTNode* Lchild, * Rchild; }BTNode;
先序遍历:
分别展示 递归算法和非递归算法
//DLR先序遍历(根节点 左 右) LDR中序遍历 LRD后序遍历 //分别讨论递归算法和非递归算法 void PreorderTranspose(BTNode* T) { if (T != NULL) { visit(T->data); PreorderTranspose(T->Lchild); PreorderTranspose(T->Rchild); } } //先序遍历 非递归算法 一次遍历中 左 记录下右节点 void PreorderTraverse(BTNode* T) { BTNode* Stack[MAX_NODE], * p=T, * q; int top = 0; if (T == NULL) cout << "Binary Tree is Empty!" << endl; else { do { visit(p->data); q = p->Rchild; if (q != NULL)Stack[++top] = q; p = p->Lchild; if (p == NULL) { p = Stack[top]; top--; } } while (p != NULL); } }
中序遍历:
分别展示 递归算法和非递归算法
//中序遍历 左 根 右 void InorderTraverse(BTNode* T) { if (T != NULL) { InorderTraverse(T->Lchild); visit(T->data); InorderTraverse(T->Rchild); } } //中序遍历 非递归算法 Stack存储根节点 void IreorderTraverse(BTNode* T) { BTNode* Stack[MAX_NODE], * p=T; int top = 0, bool = 1; if (T == NULL) cout << "Binary Tree is Empty!" << endl; else { do { while(p!=NULL) { Stack[++top] = p; p = p->Lchild; } if (top == 0)bool = 0; else { p = Stack[top]; top--; visit(p->data); p = p->Rchaild; } } while (bool != 0); } }
后序遍历
分为递归和非递归
//后序遍历 左 右 根 void PostorderTraverse(BTNode* T) { if (T != NULL) { PostorderTraverse(T->Lchild); PostorderTraverse(T->Rchild); visit(T->data); } } void PostorderTranverse(BTNode* T) { BTNode* Sa[MAX_NODE], * p = T; int Sb[MAX_NODE], top = 0, bool = 1; if (T == NULL)cout << "Binary Tree is Empty!" << endl; else { do { while (p != NULL) { Sa[++top] = p; Sb[top] = 0; p = p->Lchild; } if (top == 0)bool = 0; else if(Sb[top]==0) { p = Sa[top]->Rchild; Sb[top] = 1; } else { p = Sa[top]; top--; visit(p->data); p = NULL; } } while (bool != 0); } }
4 二叉树的层次遍历,遵循自上而下,自左而右的遍历方式。
//层次二叉树 遍历 自上而下 自左而右 void LevelorderTraverse(BTNode* T) { BTNode* Queue[MAX_NODE], * p = T; int front = 0; rear = 0; if (p != NULL) { Queue[++rear] = p; while (front < rear) { p = Queue[++front]; visit(p->data); if (p->Lchild != NULL) Queue[++rear] = p->Lchild; if (p->Rchild != NULL) Queue[++rear] = p->Rchild; } } }
5 建二叉树
层次建树:遵循自上而下,自左而右,返回根指针
//按照满二叉树链表创建 返回指向根节点的指针变量 自上而下 自左而右 BTNode* Create_BTree(void) { BTNode* T, * p, * s[MAX_NODE]; char ch; int i, j; while (true) { cin >> i; if (i == 0)break; else { cout << "请输入字符" << endl; cin >> ch;; p = (BTNode*)malloc(sizeof(BTNode)); p->data = ch; p->Lchild = p->Rchild = NULL; s[i] = p; if (i == 1)T = p; else { j = ceil(i / 2); if (i % 2 == 0)s[j]->Lchild = p; else s[j]->Rchild = p; } } } return T; }
按照先序方式建立二叉树:
//按照先序遍历方式 建立 BTNode* Preorder_Create_BTree(BTNode* T) { char ch; cout << "" << endl; cin >> ch; if(ch==NULLKY) { T = NULL; return(T); } else { T = (BTNode*)malloc(sizeof(BTNode)); T->data = ch; Preorder_Create_BTree(T ->Lchild); Preorder_Create_BTree(T ->Rchild); return T; } }
6 求二叉树的叶子节点和深度
二叉树的叶子节点是 度为0的节点。叶子是指出度为0的结点,又称为终端结点。
//求二叉树的叶子节点数 先找的左下的叶子节点 int search_leaves(BTNode* T) { BTNode* Stack[MAX_NODE], * p = T; int top = 0, num = 0; if (T != NULL) { stack{ ++top } = p; while (top > 0) { p = stack[top--]; //当节点左右节点都是NULL时,Stack中这个节点位置都会被左节点替代,从而跨越到本届点的右边 if (p->Lchild == NULL && p->Rchild == NULL) num++; if (p->Rchild != NULL) stack[++top] = p->Rchild; if (p->Lchild != NULL) stack[++top] = p->Lchild; } } return num; }
深度:
高度和深度是相反的表示,深度是从上到下数的,而高度是从下往上数。
我们先来看看高度和深度的定义,某节点的深度是指从根节点到该节点的最长简单路径边的条数,而高度是指从该节点到叶子节点的最长简单路径边的条数。
注意:这里边的条数是规定根节点的深度和叶子节点的高度是0;
所以树的深度和高度是相等的,而对其他节点来说深度和高度不一定相等。
//求二叉树的深度 利用层次遍历法可以直接求二叉树的深度 int search_depth(BTNode* T) { BTNode* Stack[MAX_NODE], * p = T; int front = 0, rear = 0, depth = 0, level; if (T != NULL) { Queue[++rear] = p; level = rear; while (front < rear) { p = Queue[++front]; if (p->Lchild != NULL) Queue[++rear] = p; if (p->Rchild != NULL) Queue[++rear] = p; if(front==level) { depth++; level = rear; } } } }