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();
}
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();
}