算法导论9.1-1习题解答(二叉树)

CLRS 9.1-1 :

证明:在最坏情况下,利用n + [lgn] - 2此比较,即可找到n个元素中的第2小元素。(提示:同时找最小元素)

算法思想:

1.将数组中的元素分组,每组两个元素,然后比较每组中的两个元素得到最小值,重新得到包含原来一半元素的数组,继续重复上述过程,那么最后一个元素必然为最小值。如图所示,数组为{2, 1, 4, 3, 5}

2.上述过程形成的是一个二叉树,其中叶子节点都为数组元素,非叶子节点刚好4个,这是二叉树的性质。

3.然后我们来找第二小元素,第二小元素必然跟着1,首先赋值为5,然后再赋值为3, 然后赋值为2,即为所求。

PS:本章讨论的元素都互异,不存在相同值(见原书)

#include < iostream >
using  namespace std;
class Node
{
public :
  Node
* left;
  Node
* right;
  int data;
  Node();
  Node(
int d);
};
class BinaryTree
{
public :
  Node
* root;
  // 创建树
  void create_tree(Node ** node, int len);
  // 求最小值
  int min( int a, int b);
  // 寻找第二小值
  int search_second_small();
  BinaryTree();
};
int main()
{
  int arr[ 10 ] = { 89 , 123 , 7 , 9 , 2 , 5 , 25 , 8 , 43 , 23 };

  // 叶子节点
  Node ** node = new Node * [ 10 ];
  for ( int i = 0 ; i < 10 ; i ++ )
    node[i]
= new Node(arr[i]);
  BinaryTree
* bi_tree = new BinaryTree();
  bi_tree
-> create_tree(node, 10 );
  cout
<< bi_tree -> root -> data << endl;
  cout
<< bi_tree -> search_second_small() << endl;
  return  0 ;
}
Node::Node()
{
  left
= right = NULL;
}
Node::Node(
int d)
{
  data
= d;
  left
= right = NULL;
}
void BinaryTree::create_tree(Node ** node, int len)
{
  // len == 2时,就剩下两个元素进行比较了,得到最后一个元素为root节点,即最小值节点
  if (len == 2 )
  {
    root
-> left = node[ 0 ];
    root
-> right = node[ 1 ];
    root
-> data = min(node[ 0 ] -> data, node[ 1 ] -> data);
  }
  else
  {
    int new_len = (len % 2 ) ? (len / 2 + 1 ) : len / 2 ;
    Node
** new_node = new Node * [new_len];
    // new_node元素个数为奇数
    if (len % 2 )
    {
      for ( int i = 0 ; i < new_len - 1 ; i ++ )
      {
        // 构建父亲节点
        new_node[i] = new Node(min(node[ 2 * i] -> data, node[ 2 * i + 1 ] -> data));
        new_node[i]
-> left = node[ 2 * i];
        new_node[i]
-> right = node[ 2 * i + 1 ];
      }
      new_node[new_len
- 1 ] = node[len - 1 ];
    }
    // new_node元素个数为偶数
    else
    {
      for ( int i = 0 ; i < new_len; i ++ )
      {
        // 构建父亲节点
        new_node[i] = new Node(min(node[ 2 * i] -> data, node[ 2 * i + 1 ] -> data));
        new_node[i]
-> left = node[ 2 * i];
        new_node[i]
-> right = node[ 2 * i + 1 ];
      }
    }
    create_tree(new_node, new_len);
    delete[] new_node;
  }
}
int BinaryTree::min( int a, int b)
{
  return a < b ? a : b;
}
int BinaryTree::search_second_small()
{
  int second = 1000000 ;
  Node
* p = root;
  while (p -> left != NULL && p -> right != NULL)
  {
    if (p -> data == p -> left -> data && second > p -> right -> data)
    {
      second
= p -> right -> data;
      p
= p -> left;
    }
    else  if (p -> data == p -> right -> data && second > p -> left -> data)
    {
      second
= p -> left -> data;
      p
= p -> right;
    }
    else
      return second;
  }
  return second;
}
BinaryTree::BinaryTree()
{
  root
new Node();
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值