[C++]封装排序二叉树&随机数生成(c++11)

来源:互联网 发布:达内编程培训 编辑:程序博客网 时间:2024/05/01 04:44

封装排序二叉树&随机数生成(c++11)

本文,我尝试着把排序二叉树封装为一个模板类,并且用C++11给出的随机数生成函数来对这个类进行测试。

排序二叉树封装

这个二叉树的特征是,左子数的值肯定比父节点小,右子树的值肯定比父节点的大。要求大家按照这个结构特征去构建二叉树,最后中序遍历输出就是我们要求的升序输出。

我们可以根据具体的要求来完成对排序二叉树的构建,可以用一个bool函数来区别不同排序顺序,默认是升序。紧接着用递归来不断地insert新的节点。最后用中序遍历就可以得到我们需要的排序结果。如果想要改变visit输出方式,要也可以设定一个函数指针。不过因为封装性,还需要在类里面增加对Node的内部访问。

////  main.cpp//  排序////  Created by 颜泽鑫 on 5/9/16.//  Copyright © 2016 颜泽鑫. All rights reserved.//#include <iostream>#include <vector>#include <random>#include <time.h>#include <algorithm>#include <iomanip>using namespace std;template <typename T>bool cmps(T a, T b);template <typename T>class BinaryTree {public:    struct Node {        T value;        Node* left;        Node* right;        Node(T vals = 0, Node* lefts = NULL, Node* rights = NULL) : value(vals), left(lefts), right(rights) {        }    };    BinaryTree(const std::vector<T>& orig, bool (*cmp)(T a, T b) = cmps<T>);    ~BinaryTree();    void print();private:    Node* root;    void insert(Node* root, T value, bool (*cmp)(T a, T b));    void clear(Node* temp);    void visit(Node* root);};template <typename T>bool cmps(T a, T b) {    if (a <= b) {        return true;    } else {        return false;    }}template <typename T>void BinaryTree<T>::insert(BinaryTree::Node *root, T value, bool (*cmp)(T a, T b)) {    if (cmp(value, root->value)) {        if (root->left == NULL) {            Node* temp = new Node(value);            root->left = temp;        } else {            insert(root->left, value, cmp);        }    } else {        if (root->right == NULL) {            Node* temp = new Node(value);            root->right = temp;        } else {            insert(root->right, value, cmp);        }    }}template <typename T>BinaryTree<T>::BinaryTree(const std::vector<T>& orig, bool (*cmp)(T a, T b)) {    root = new Node(orig[0]);    for (int i = 1; i != orig.size(); i++) {        insert(root, orig[i], cmp);    }}template <typename T>void BinaryTree<T>::clear(Node* root) {    if (root != NULL) {        clear(root->left);        clear(root->right);        delete root;    }}template <typename T>BinaryTree<T>::~BinaryTree() {    clear(root);}template <typename T>void BinaryTree<T>::visit(BinaryTree::Node *root) {    if (root != NULL) {        visit(root->left);        std::cout << root->value << " ";        visit(root->right);    }}template <typename T>void BinaryTree<T>::print() {    visit(root);}

测试函数:

int main() {    int range;    std::cin >> range;    int total_num = range;    std::vector<double> input;    std::random_device ram;    std::uniform_real_distribution<> dis(1, range);    double value = 0;    while (total_num--) {        value = dis(ram);        input.push_back(value);    }    BinaryTree<double> tree(input);    tree.print();    return 0;}

随机数生成类

接下来我们讨论随机数的生成方法。

在C++11中给出了一个新的特性来完成随机数的生成。

1. random_device

标准库提供了一个非确定性随机数生成设备.在Linux的实现中,是读取/dev/urandom设备;Windows的实现居然是用rand_s,在这里强烈谴责一下.

random_device提供()操作符,用来返回一个min()到max()之间的一个数字.如果是Linux(Unix Like或者Unix)下,都可以使用这个来产生高质量的随机数,可以理解为真随机数.

#include <iostream>#include <random>int main() {  std::random_device rd;  for(int n=0; n<20000; ++n)    std::cout << rd() << std::endl;  return 0; }

2. random number engine

标准把随机数抽象成随机数引擎分布两部分.引擎用来产生随机数,分布产生特定分布的随机数(比如平均分布,正太分布等).

标准提供三种常用的引
擎:linear_congruential_engine,mersenne_twister_engine和subtract_with_carry_engine.第一种是线性同余算法,第二种是梅森旋转算法,第三种带进位的线性同余算法.第一种是最常用的,而且速度也是非常快的; 第二种号称是最好的伪随机数生成器;第三种没用过….

随机数引擎接受一个整形参数当作种子,不提供的话,会使用默认值. 推荐使用random_device来产生一个随机数当作种子.(windows下爱咋整咋整,谁叫windows的random_device是调用rand_s)

#include <iostream>#include <random>int main(){  std::random_device rd;  std::mt19937 mt(rd());  for(int n = 0; n < 10; n++)    std::cout << mt() << std::endl;  return 0;}

3. random number distributions

标准提供各种各样的分布,不过我们经常用的比较少,比如平均分布,正太分布…使用也很简单

//平均分布#include <random>#include <iostream>int main(){    std::random_device rd;    std::mt19937 gen(rd());    std::uniform_int_distribution<> dis(1, 6);    for(int n=0; n<10; ++n)        std::cout << dis(gen) << ' ';    std::cout << '\n';}
//正态分布#include <iostream>#include <iomanip>#include <string>#include <map>#include <random>#include <cmath>int main() {    std::random_device rd;    std::mt19937 gen(rd());    // values near the mean are the most likely    // standard deviation affects the dispersion of generated values from the mean    std::normal_distribution<> d(5,2);    std::map<int, int> hist;    for(int n=0; n<10000; ++n) {        ++hist[std::round(d(gen))];    }    for(auto p : hist) {        std::cout << std::fixed << std::setprecision(1) << std::setw(2)                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';    }}
0 0