数据结构习题整理(4.0)

42.试着写出一个判定给定二叉树是否为二叉排序树的算法。设此二叉树以二叉链表作存储结构,且树中结点的关键字均不同。

int isbstree(bitree t)/*判断是否为二叉排序树*/

{

if(t->lchild && flag)

isbstree(t->lchild);

if(t->data.key<storenum)

flag=0;//左子树一支中若父节点的值小于子节点,则flag为0

storenum=t->data.key;//更新storenum的值

if(t->rchild && flag)

isbstree(t->rchild);

return flag;

}

43.(二叉排序树)求出指定结点在给定二叉树的层次

 

int  Level(BSTree *root,int k){

int height=0;

if(!root)

return 0;

while (root){

 

if(root->data==k){

height++;

break;

}

else if(root->data>k){

height++;

root=root->lchild;

}

else{

height++;

root=root->rchild;

}

}

if(!root)

return 0;

else

return height;

}

44.试编写一算法在给定的二叉排序树上找出任意两个不同结点最近的公共祖先(若在两结点A,B中,A是B的祖先,则认为A,B最近的公共祖先就是A)。

45.试写一时间复杂度为O(log2n+m)的算法,删除二叉排序树中所有关键字不小于x的结点,并释放结点空间。其中n为树中所含结点数,m为被删除的结点个数。

46.二叉排序树BT采用二叉链表方式存储,编写一个二叉排序树上插入结点的非递归算法。

47.在平衡二叉树中的每个结点上增设一个Lsize域,其值为它的左子树中的结点个数加1,试写一个时间复杂度为O(log n)的算法,确定树中第k个结点的位置。

 

二叉排序树中第k个结点,即为二叉排序树中序序列中顺序号为k的结点,根结点的Lsize域中存放的是根结点的顺序号。要确定二叉排序树中第k个结点,先需将k与根结点的顺序号进行比较,若相等,则找到;若k小于根结点的顺序号,k继续与根的左孩子结点的顺序号比较,依次类推。(注意,右孩子结点的顺序号等于根结点的顺序号与右孩子结点的Lsize域值之和。)由于查找过程中不超过树的高度,故其算法复杂度为O(log n)。

typedef struct Node{

int key:

struct Node* lchild,*rchild:

int Lsize

}BSNode;

BSNode* Locate(BSNode* T,int k)

{

int j,i=0;

BSNode* p=T;

while(p)

{

j=i+p->Lsize;

if(j==k) return p;//找到

if(j>k) p=p->lchild;

else{

i+=p->Lsize;

p=P->rchild;

}

}

return NULL:

}

48.试推导含12个结点的平衡二叉树的最大深度,并画出一棵这样的树。

49.试从空树开始,画出按以下次序向2-3树即3阶B-树中插入关键码的建树过程:20,30,50,52,60,68,70。如果此后删除50和68,画出每一步执行后2-3树的状态。

50.含9个叶子结点的3阶B-树中至少有多少个非叶子结点?含10个叶子结点的3阶B-树中至少有多少个非叶子结点?

9个叶子结点正好3层,有4个非叶子结点.

10个叶子结点需4层,有6个非叶子结点.

51.已知一组关键字{40,27,28,12,15,50,7},要求采用堆排序从小到大排序。

(1)请画出建立初始堆的过程图示

(2)请画出前三趟排序的过程图示。

52.关键字序列{503,087,512,061,908,170,897,275,653,426}堆排序。

53.插入排序中寻找插入位置的操作可以通过二分查找的方法来实现,设计一个使用二分查找法找插入位置的改进的插入排序算法

 

#include<iostream>

using namespace std;

void sort(int arr[], int n){

 int low, high, place, temp;

 for(int i = 1; i < n; ++i){

  low = 0, high = i - 1;

  temp = arr[i];

while(low <= high){

int mid = (low + high) / 2;

if(temp <= arr[mid]){

high = mid - 1;

}else{

low = mid + 1;

}

}

//说明关键字应该是插入到low这个位置的所以low这个位置

place = low;

//注意应该是j >= place

for(int j = i - 1; j >= place; --j){

arr[j + 1] = arr[j];

}

arr[place] = temp;

 }

}

 

int main(void){

int arr[9] = {3, 5, 1, 2, 7, 9, 12, 14, 8};

sort(arr, 9);

for(int i = 0; i < 9; ++i){

cout << arr[i] << " ";

}

cout << endl;

return 0;

}

54.在待排序的元素序列基本有序的前提下,效率最高的排序方法是(A)。

 

A.冒泡排序

B.选择排序

C.快速排序

D.归并排序

 

55.为什么通常使用一维数组作为堆的存放形式

堆是一个满二叉树,在内存中是连续存储的,所以用数组来表示非常合适

56.试问如下6种排序方法中,哪些是稳定的?哪些是不稳定的?

(1)直接插入排序;

(2)希尔排序(增量d[1]=5);

(3)快速排序;

(4)堆排序;

(5)归并排序;

(6)基数排序

希尔排序、快速排序和堆排序是不稳定的排序方法。

57.(1)、排序(分类)的方法有许多种:__A_③_法从未排序序列中依次取出元素,与排序序列(初始为空)中的元素作比较,将其放入已排序列的正确位置上;__B①__法从未排序序列中挑选元素,并将其依次放入已排序序(初始时为空)的一端;交换排序法是对序列中元素进行一系列的比较,当被比较的两元素逆序时进行交换。__C_④__和__D②__是基于这类方法的两种排序方法,而__D_②_是比__C_④_效率更高的方法,利用某种算法,根据元素的关键值计算出排序位置的方法是__E_⑦_。

① 选择排序 ② 快速排序 ③ 插入排序 ④ 冒泡排序 ⑤ 归并排序 ⑥ 二分排序 ⑦ 哈希排序 ⑧ 基数排序

(2)、一组记录的关键字为(46,79,56,38,40,84),利用快速排序的方法,以第一个记录为基准得到的一次划分结果为 C 。

 A、38,40,46,56,79,84

 B、40,38,46,79,56,84

 C、40,38,46,56,79,84

 D、40,38,46,84,56,79

(3)、下列排序算法中, C 算法可能会出现下面情况:初始数据有序时,花费时间反而最多。

 

A、堆排序 B、冒泡排序 C、快速排序 D、SHELL 排序

58.判断正误:

 

1.在一个大堆中,最小元素不一定在最后。(√)

2.对n个记录采用快速排序方法进行排序,最坏情况下所需时间是o(nlog2n)。 ( x )

3.在执行某排序算法过程中,出现了排序码朝着与最终排序序列相反方向移动的现象,则称该算法是不稳定的。(×)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mez_Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值