目录
1. 二叉树(binary tree)
数组+链表=树
数组:易于查找,不易插入删除。链表:易于插入删除,不易直接查找。
二叉树是节点度数不超过2的树。如果每个节点都是2,则是满二叉树。用二叉树表示任何一颗树。
完全二叉树:最多只有最小面的两层节点度数小于2,最小一层的结点都集中在最左边。
BinNode
模板类
构建最大堆
2. 深度优先搜索
二叉树结点ADT
template<class T>
class BinaryTreeNode{
friend class BinaryTree<T>;
private:
T info;
public:
BinaryTreeNode();
BinaryTreeNode(const T& ele);
BinaryTreeNode(const T& ele, BinaryTreeNode<T> *l, BinaryTreeNode<T> *r);
T value() const;
BinaryTreeNode<T> *leftchild() const;
BinaryTreeNode<T> *rightchild() const;
。。。
}
二叉树ADT
template<class T>
class BinaryTree{
private:
BinaryTreeNode<T>* root;
public:
BinaryTree() {root = NULL};
~BinaryTree() {DeleteBinaryTree(root)};
bool isEmpty() const;
BinaryTreeNode<T>* Root() {return root};
。。。
};
三种深度优先遍历的递归定义:
前序法(tLR次序,preorder traversal):访问根节点,左子树,右子树。
中序法(LtR次序,inorder traversal):左子树,根节点,右子树。
后序法(LRt次序,postorder traversal):左子树,右子树,根节点。
2.1 递归遍历二叉树
template<class T>
void BinaryTree<T>::DepthOrder (BinaryTreeNode<T>* root)
{
if(root != NULL){
Visit(root);//访问结点本身的,前序
DepthOrder(root->leftchild());//递归访问左子树
Visit(root);//访问结点本身的,中序
DepthOrder(root->rightchild());//递归访问右子树
Visit(root);//访问结点本身的,后序
}
}
2.2 非递归前序遍历二叉树
思想:
1)遇到一个结点,就访问该结点,并把此结点的非空右节点推入栈中,然后下降去遍历它的左子树;
2)遍历完左子树后,从栈顶托出一个结点,并按照它的右链接指示地址再去遍历该结点的右子树。
template<class T>
void BinaryTree<T>::PreOrderWithoutRecusion (BinaryTreeNode<T>* root)
{
using std::stack;//使用STL中的stack
stack<BinaryTreeNode<T>* > aStack;
BinaryTreeNode<T>* pointer = root;
aStack.push(NULL);//栈底监视哨
while(pointer){//或者!aStack.empty(),当前结点非空
Visit(pointer->value);//访问当前结点
if(pointer->rightchild() != NULL)//右孩子不空,右孩子入栈
aStack.push(pointer->rightchild());
if(pointer->leftchild() != NULL)//左孩子不空
pointer = pointer->leftchild();//左路下降
else{//左孩子空,左树访问完毕,转向访问右子树
pointer = aStack.top();
aStack.pop();//栈顶元素退栈
}
}
}
2.3 非递归中序遍历二叉树
思想:
1)遇到一个结点,把它推入栈中,遍历其左子树;
2)遍历完左子树,从栈顶脱出该结点并访问,按照其右链地址遍历该结点的右子树
template<class T>
void BinaryTree<T>::PreOrderWithoutRecusion (BinaryTreeNode<T>* root)
{
using std::stack;//使用STL中的stack
stack<BinaryTreeNode<T>* > aStack;
BinaryTreeNode<T>* pointer = root;
aStack.push(NULL);//栈底监视哨
while(!aStack.empty() || pointer){//当前栈非空或者当亲结点非空
if(pointer){//
Visit(pointer->value);
aStack.push(pointer);//推入栈中
pointer = pointer->leftchild();
}else if{//左子树访问完毕,转向访问右子树
pointer = aStack.top();
aStack.pop();//栈顶元素退栈
Visit(pointer->value);
pointer = pointer->rightchild();
}
}
}
2.4 非递归后序遍历二叉树
思想:
1)
2)
3. 宽度优先遍历二叉树
从二叉树的第0层(根节点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问。
4. 二叉树的存储结构
二叉链表:指针left
和right
,分别指向结点的左孩子和右孩子。
三叉链表:指针left
和right
,分别指向结点的左孩子和右孩子。增加一个父指针。
二叉链表的存储结构
template<class T>
class BinaryTreeNode{
friend class BinaryTree<T>;
private:
T info;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
public:
BinaryTreeNode();
BinaryTreeNode(const T& ele);
BinaryTreeNode(const T& ele, BinaryTreeNode<T> *l, BinaryTreeNode<T> *r);
T value() const;
BinaryTreeNode<T> *leftchild() const;
BinaryTreeNode<T> *rightchild() const;
。。。
}
通过递归框架寻找父节点。
完全二叉树的下标公式
5. 二叉搜索树
定义:
6. 堆与优先队列
最小堆是一个关键码序列,对于任意一个结点,该结点的值既小于左孩子也小于右孩子。
堆的性质:
1)完全二叉树的层次序列,可以用数组表示。
2)堆中存储的数是局部有序的,堆不唯一。结点的值与其孩子的值存在限制,任何一个结点与其兄弟之间没有限制。
3)从逻辑角度看,堆实际上是一种树形结构。