2022年10月9日 开学第五周博客

目录

一:本周总结:

二:二叉树:

1.1:树的递归定义:

1.2:有序二叉树

 1.2.1二叉树的查找

1.2.2 二叉树的遍历

1.2.3 二叉树的插入

1.2.4 合并删除、

1.2.5 复制删除

1.2.6树的平衡


一:本周总结:

本周我看完了二叉树,刚看到其他同学的博客已经看完了线段树,感觉自己落后了,下周争取看完AVL树

二:二叉树:

1.1:树的递归定义:

a:空结构是一棵树。

b:如果t1.t2.....tk是不相交的树,那么,根节点以t1.t2......tk作为子节点的数据结构也是一棵树

c:只有通过a,b产生的数据结构才是树

注:和现实生活中的树不同,这里的树是倒过来的,根在顶部

1.2:有序二叉树

对于树的每一个节点n,其左子树中的值小于节点n中的值v,其右子树的值大于节点n中的值。

 1.2.1二叉树的查找

最坏情况是树转化为链表,复杂度O(n);

将要定位的键值与房前所指向的节点的存储值进行比较,如果键值小于存储值,则转向左子树,如果键值比存储值大,则转向右子树,如果二者相同,搜索可以终止了。如果没有其他节点,搜索也可以终止了,表示键值不在该树中。

template<typename T>
T* BST<T>::BSTsearch(BSTNode<T>* p, const T& el) const
{
	while (p!=0)
	{
		if (el == p->key)
		{
			return &p->k;
		}
		else if (el < p->key)
		{
			p = p->left;
		}
		else
		{
			p = p->right;
		}
	}
	return nullptr;
}

1.2.2 二叉树的遍历

节点有多少种排列方式,就有多少种遍历方法,对于有n个节点的树,共有n!种遍历方式,他们大多数无序且混乱。很显然,这样的遍历是毫无意义的。比较有用的是广度优先遍历和深度优先遍历

广度优先遍历:

使用队列进行树的遍历,假设从上到下,从左到右进行广度优先遍历,使用队列,在访问一个节点后,他的子节点就放到队列的末尾,然后访问队列头部的节点。对于层次为n的节点,它的子节点位于第n+1层,如果将该节点的所有子节点都放到了队尾,那么,这些节点就将在第n层节点访问后再访问。

template<typename T>
void BST<T>::breadFirst()
{
	queue<BSTNode<T>*>queue;
	BSTNode<T>* p = root;
	if (p != 0)
	{
		queue.push(p);
	}
	while (!queue.empty())
	{
		p = queue.front();
		queue.pop();
		cout << p->key << " ";
		if (p->left != 0)
		{
			queue.push(p->left);
		}
		if (p->right != 0)
		{
			queue.push(p->right);
		}
	}
}

深度优先遍历:

深度优先遍历分为前序遍历,中序遍历,后序遍历三种遍历方式

一下是用双重递归实现的三种遍历方式

template<typename T>
void BST<T>::innorder(BSTNode<T>* p)
{
	if (p != 0)
	{
		innorder(p->left);
		cout << p->key << " ";
	}
}

template<typename T>
void BST<T>::preorder(BSTNode<T>* p)
{
	if (p != 0)
	{
		cout << p->key << " ";
		preorder(p->left);
		preorder(p->right);
	}
}

template<typename T>
void BST<T>::postorder(BSTNode<T>* p)
{
	if (p != 0)
	{
		postorder(p->left);
		postorder(p->right);
		cout << p->key << " ";
	}
}

1.2.3 二叉树的插入

和搜索树相同,在扫描树的过程中,比较键值el与当前节点的键值,如果el小于该键值,就测试当前节点的左节点,否则,就测试当前节点的右节点。如果要测试的p的子节点为空,就停止扫描,使新节点成为p的子节点。

template<class T>
void BST<T>::insert(const T& el) {   
    BSTNode<T> *p = root, *prev = 0;
    while (p != 0) {        // find a place for inserting new node;
        prev = p;
        if (p->key < el)
             p = p->right;
        else p = p->left;
    }
    if (root == 0)    // tree is empty;
         root = new BSTNode<T>(el);
    else if (prev->key < el)
         prev->right = new BSTNode<T>(el);
    else prev->left  = new BSTNode<T>(el);
}

1.2.4 合并删除、

找到左子树具有最小值的节点,使之成为右子树的父节点。同理 可以赵右子树的最小值的节点,使之成为左子树的父节点。

把指针一直按照一个方向移动,直到遇到空指针。

template<class T>
void BST<T>::deleteByMerging(BSTNode<T>*& node) {   
    BSTNode<T> *tmp = node;
    if (node != 0) {
        if (!node->right)           // node has no right child: its left
             node = node->left;     // child (if any) is attached to its parent;
        else if (node->left == 0)   // node has no left child: its right
             node = node->right;    // child is attached to its parent;
        else {                      // be ready for merging subtrees;
             tmp = node->left;      // 1. move left
             while (tmp->right != 0)// 2. and then right as far as possible;
                tmp = tmp->right;
             tmp->right =           // 3. establish the link between the
                node->right;        //    the rightmost node of the left
                                    //    subtree and the right subtree;
             tmp = node;            // 4.
             node = node->left;     // 5.
        }
        delete tmp;                 // 6.
     }
}

template<class T>
void BST<T>::findAndDeleteByMerging(const T& el) {    
    BSTNode<T> *node = root, *prev = 0;
    while (node != 0) {
        if (node->key == el)
             break;
        prev = node;
        if (node->key < el)
             node = node->right;
        else node = node->left;
    }
    if (node != 0 && node->key == el)
         if (node == root)
              deleteByMerging(root);
         else if (prev->left == node)
              deleteByMerging(prev->left);
         else deleteByMerging(prev->right);
    else if (root != 0)
         cout << "key " << el << " is not in the tree\n";
    else cout << "the tree is empty\n";
}

1.2.5 复制删除

果要删除的节点有两个子节点,该问题就可以简化为如下两个简单问题之一:要删除的节点是叶子节点,或要删除的节点只有一个非空子节点。为此,可以用该节点的直接前驱(或后继)替换要删除的键。如合并删除算法所示,键值的前驱是其左子树中最右侧节点的键值(同样,它的直接后继是其右子树中最左侧节点中的键值)。首先需要定位前驱。为此,仍然需要向左移-步,首先找到要删除节点的左子树的根,再尽可能地向右移动。接下来,用找到的节点的键值替换要删除的键值。这时需要区分两种简单情况:如果最右侧的节点是一个叶子节点,就是第一种情况;如果它有一个子节点,就是第二种情况。这样,复制删除算法用键值k2覆盖键值kq,从而删除键值k1,再删除包含键值k2的节点;而合并删除算法会删除键值k1以及包含该键值的节点。

template<class T>
void BST<T>::deleteByCopying(BSTNode<T>*& node) {    
    BSTNode<T> *previous, *tmp = node;
     if (node->right == 0)                  // node has no right child;
          node = node->left;   
     else if (node->left == 0)              // node has no left child;
          node = node->right;
     else {
          tmp = node->left;                 // node has both children;
          previous = node;                  // 1.
          while (tmp->right != 0) {         // 2.
              previous = tmp;
              tmp = tmp->right;
          }
          node->key = tmp->key;             // 3.
          if (previous == node)
               previous->left  = tmp->left;
          else previous->right = tmp->left; // 4.
     }
     delete tmp;                            // 5.
}

// findAndDeleteByCopying() searches the tree to locate the node containing
// el. If the node is located, the function DeleteByCopying() is called.

template<class T>
void BST<T>::findAndDeleteByCopying(const T& el) {    
    BSTNode<T> *p = root, *prev = 0;
     while (p != 0 && !(p->key == el)) {
         prev = p;
         if (p->key < el)
              p = p->right;
         else p = p->left;
     }
     if (p != 0 && p->key == el)
          if (p == root)
               deleteByCopying(root);
          else if (prev->left == p)
               deleteByCopying(prev->left);
          else deleteByCopying(prev->right);
     else if (root != 0)
          cout << "key " << el << " is not in the tree\n";
     else cout << "the tree is empty\n";
}

1.2.6树的平衡

低效率的算法(额外数组 重建树)

template<class T>
void BST<T>::balance (T data[], int first, int last) {
    if (first <= last) {
        int middle = (first + last)/2;
        insert(data[middle]);
        balance(data,first,middle-1);
        balance(data,middle+1,last);
    }
}

DSW算法:

if Par 不是树的根节点 

        子节点CH的祖父节点Gr成为Ch的父节点;

Ch的右子树成为Ch的父节点Par的左子树;

节点Ch把Par作为它的右子节点;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值