数据结构与算法要点总结(7):静态搜索表、二叉搜索树、AVL树

本文详细介绍了顺序搜索中的监视哨方法、二叉搜索树的中序遍历、搜索和插入算法,以及AVL树的定义、平衡因子、平衡化旋转和插入/删除操作。这些内容对IT技术面试和理解基础数据结构有帮助。
摘要由CSDN通过智能技术生成

目录

1、静态搜索表

顺序搜索

监视哨

顺序搜索的平均搜索长度 

折半搜索

2、二叉搜索树

二叉搜索树的中序遍历

二叉搜索树上的搜索

二叉搜索树的插入算法

笔试模拟建树过程:

二叉搜索树的删除

3、AVL树

定义:

平衡因子:

平衡化旋转

AVL树的插入

AVL树的删除


1、静态搜索表

顺序搜索

一般的顺序搜索可见要点总结(2),在此介绍一种使用“监视哨”的顺序搜索方法。

监视哨

设在数据表 dataList 中顺序搜索关键码与 给定值 x 相等的数据元素,要求数据元素在表中从下标 0 开始存放, 下标为 CurrentSize 的元素作为控制搜索过程自动结束的“监视哨”使用。

若搜索成功,则函数返回该元素在表中序号 Location(比下标大 1), 若搜索失败,则函数返回 CurrentSize+1。  

template <class E, class K>
int dataList<E, K>::SeqSearch (const K x) const {
     Element[CurrentSize].key = x;
	 int i = 0;		                    //将x设置为监视哨
     while (Element[i].key != x) i++;				                                        //从前向后顺序搜索
     return i+1;
};

const int Size = 10;
main () {
     dataList<int> L1 (Size);	//定义int型搜索表L1
     int Target;  int Loc;
     cin >> L1;  cout << L1;	//输入L1 
     cout << “Search for a integer : ”;
     cin >> Target;			//输入要搜索的数据 
	 if ( (Loc = L1.Seqsearch(Target)) <= 
              L1.Length() )	
          cout << “找到待查元素位置在:” << Loc+1
                 << endl;		//搜索成功
     else cout << “ 没有找到待查元素\n”;
                                                   //搜索不成功
};
顺序搜索的平均搜索长度 

 

折半搜索

为了加速搜索,在有序顺序表的情形,可以采用折半搜索,它也称二分搜索,时间代价可减到O(log_2n)

折半搜索具体内容可见要点总结(6)中的字典部分

2、二叉搜索树

二叉搜索树的中序遍历

如果对一棵二叉搜索树进行中序遍历,可以按从小到大的顺序,将各结点关键码排列起来,所以也称二叉搜索树为二叉排序树。

二叉搜索树上的搜索

在二叉搜索树上进行搜索,是一个从根结点开始,沿某一个分支逐层向下进行比较判等的过程。它可以是一个递归的过程。

  • 假设想要在二叉搜索树中搜索关键码为 x 的元素,搜索过程从根结点开始。
  • 如果根指针为NULL,则搜索不成功;否则用给定值 x 与根结点的关键码进行比较:
  • 若给定值等于根结点关键码,则搜索成功,返回搜索成功信息并报告搜索到结点地址。
  • 若给定值小于根结点的关键码,则继续递归搜索根结点的左子树;
  • 否则。递归搜索根结点的右子树。

非递归的写法也比较容易:

template<class E, class K>
BSTNode<E, K>* BST<E, K>::
Search (const K x, BSTNode<E, K> *ptr) {
//非递归函数:作为对比,在当前以ptr为根的二
//叉搜索树中搜索含x的结点。若找到,则函数返
//回该结点的地址,否则函数返回NULL值。
    if (ptr == NULL) return NULL; 
    BSTNode<E, K>* temp = ptr;
    while (temp != NULL) {
        if (x == temp->data.key) return temp;
        if (x < temp->data.key) temp = temp->left;
        else temp = temp->right;
    }
    return NULL;
};

设树的高度为h,最多比较次数不超过h。

二叉搜索树的插入算法

要注意如果待插入的值已经在树中,则插入失败。

template <class E, class K>
bool BST<E, K>::Insert (const E& e1, 
       BSTNode<E, K> *& ptr) {	   
//私有函数:在以ptr为根的二叉搜索树中插入值为
//e1的结点。若在树中已有含e1的结点则不插入
    if (ptr == NULL) {	   //新结点作为叶结点插入
        ptr = new BstNode<E, K>(e1);	  //创建新结点
        if (ptr == NULL)
            { cerr << "Out of space" << endl;  exit(1); }
	    return true;
    }
    else if (e1 < ptr->data.key) Insert (e1, ptr->left);	 		//左子树插入
		 else if (e1 > ptr->data.key) Insert (e1, ptr->right);		//右子树插入
		 else return false;	      //x已在树中,不再插入
};
笔试模拟建树过程:

二叉搜索树的删除

 最复杂的是左右子树都不为空的情况,需要找在中序下的前驱或后继进行填补,然后转换为删除前驱或后继的那个节点。(所找的前驱或后继至多只有一个子女,情况简单)

中序下某节点前驱的找法:该节点的左子树的最右边的节点

中序下某节点后继的找法:该节点的右子树的最左边的节点

具体分三种情况,见图片

 

3、AVL树

即高度平衡的二叉搜索树

定义:

一棵 AVL 树或者是空树,或者是具有下列性质的二叉搜索树:它的左子树和右子树都是 AVL 树,且左子树和右子树的高度之差的绝对值不超过1。 

平衡因子:

注意:不同教材的平衡因子定义不同,在此:平衡因子定义为右子树高度减左子树高度。

平衡化旋转

如果在一棵平衡的二叉搜索树中插入一个新结点,造成了不平衡。此时必须调整树的结构,使之平衡化。

平衡化旋转有两类:

  •  单旋转 (左旋和右旋)
  •  双旋转 (左平衡和右平衡)

平衡化旋转的具体内容较为复杂,建议自行阅读相关资料进行理解,配合如下图片可以辅助记忆。

 

同时,这篇文章是为了笔试做准备,前置知识的介绍较少,待后续有空再进行补充。因此,将更多地着眼于用笔来“模拟”的过程。

AVL树的删除和插入操作都可以看成两个部分:先插入or先删除,再调整。

AVL树的插入

推荐这个动画视频,很清晰,但是注意视频中的平衡因子的定义与上下文不同。

AVL树插入视频

模拟建树过程:

如果正在期末冲刺,这个视频可能能帮到你!

关键在于回溯,以及遇到不平衡时的平衡化操作选择。

AVL树的删除

同二叉搜索树一样,仍然是分情况: 

  调整过程较为复杂,给出例题辅助理解:

可以看看这个视频:AVL树的删除

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值