• 启迪思维:链式树


    最近公司项目比较忙,又加上要给十几个新人做培训,晚上和周末又要个姐姐装修店铺(太痛苦的事情,而且装修的效果也不是很好),前些天天涯上有一篇寒门难出贵子帖子很火,那个作者语文水平和我一个级别的(错别字太多了),大家可以看淘宝鬼脚七整理版本(关注他的微信公众号),虽然里边有些观点不是很认同,但对我影响很大,出生寒门的兄弟一定去静下心来好读读,这个远比我下面写的这边技术文章带给你更多思考,非常欢迎大家留言讨论文章的观点。

    前面的文章一直在分析数据结构中线性结构部分,从本篇文章以后将进入非线性结构部分,前面未弄懂部分可以在网上找些视频结合我写的文章在补补,只有这样后面学习起来才相对容易些,下面进入正题,首先还是先分享一个软件带来误会故事。

    以前学校旁边有一个火车票代售点,每次到过年学生放假的时候,偶尔会看有人因为先买没有买到票,而后面人确买到票和售票员吵架,估计每次发生这样事情,售票员自己也解释不清楚,连当时学计算机的我也猜测后面人给售票员好处,后来偶然看到一篇帖子才明白,原来火车票售票系统,会把一定数量的票锁定给一个售票厅,前一个人买票时候,余票被其他售票厅锁住了,后面去人再买票的时候正好赶上其他售票厅释放余票(太幸运),现在技术和硬件越来越好,从09年后我就没有见过为这事吵架的。

     

    一:概念

    树状图是一种数据结构,它是由nn>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

    1每个结点有零个或多个子结点;

    2没有前驱的结点称为根结点;

    3每一个非根结点有且只有一个父结点;

    4除了根结点外,每个子结点可以分为m个不相交的子树;

     

    二:名称解释

    子孙:以某节点为根的子树中任一节点都称为该节点的子孙;

    森林:由mm>=0)棵互不相交的树的集合称为森林;

    树的度:一棵树中,最大的节点的度称为树的度;

    节点的度:一个节点含有的子树的个数称为该节点的度;

    兄弟节点:具有相同父节点的节点互称为兄弟节点;

    堂兄弟节点:双亲在同一层的节点互为堂兄弟;

    节点的祖先:从根到该节点所经分支上的所有节点;

    节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

    树的高度或深度:树中节点的最大层次;

    双亲节点或父节点:若一个结点含有子节点,则这个节点称为其子节点的父节点;

    孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;

    叶节点或终端节点:度为零的节点;

    非终端节点或分支节点:度不为零的节点;

     

    三:示例图

     

     

    四:树的应用

    1、查找算法中应用(数据库索引-B-tree)

    2、哈夫曼编码

    3、最短路径问题

    4、几乎所有的编译器都需要实现一个表达式树

    上面这些树的应用,面试中也会经常问到,争取后面能写比较好分析它们的文章

    五:树的分类

    上面的截图是维基百科里边的解释,画红框的在后面的文章会分析到;

     

    五:代码分析

    1、创建一颗树

     1 /**
     2  *根据文件内容递归创建树
     3  */
     4 void CreateTreeFromFile(ifstream &f) {
     5     //每次读取一个字符
     6     T e;
     7     InputFromFile(f, e);
     8     if (e == '#') {
     9         return;
    10     }
    11 
    12     //创建一个新的节点
    13     root = new TNode<T> (e);
    14 
    15     //创建左右两个树对象
    16     LinkTree<T> left, right;
    17     //递归创建左子树
    18     left.CreateTreeFromFile(f);
    19     //递归创建右子树
    20     right.CreateTreeFromFile(f);
    21 
    22     //设置根节点的左孩子接左子树的根节点
    23     root->lchild = left.root;
    24     left.root = 0;
    25     //设置根节点的右孩子接右子树的根节点
    26     root->rchild = right.root;
    27     right.root = 0;
    28 }
    29 /**
    30  *读取文件并赋值给遍历c
    31  */
    32 void InputFromFile(ifstream &f, T &c) {
    33     f >> c;
    34 }

    2、清空一颗树

     1 /**
     2  *清空树的所有节点
     3  */
     4 void Clear() {
     5     Clear(root);
     6 }
     7 /**
     8  *根据节点递归清空树
     9  */
    10 void Clear(TNode<T>* t) {
    11     //判断指针是否为空
    12     if (t) {
    13         //获取资源立即放入管理对象(参考Effective C++里边条款13)
    14         //tr1::shared_ptr(引用计数智慧指针)管理对象比auto_ptr更强大
    15         std::auto_ptr<TNode<T> > new_ptr(t);
    16 
    17         //递归清空右子树
    18         Clear(new_ptr->rchild);
    19 
    20         //递归清空左子树
    21         Clear(new_ptr->lchild);
    22     }
    23 
    24     //清空树的根节点
    25     t = 0;
    26 }

    3、判断树是否为空

    1 /**
    2  * 若树为空,则返回true;否则返回false
    3  */
    4 bool IsEmpty() {
    5     return root == 0;
    6 }

    4、计算树的深度

     1 /**
     2  * 以传入节点为基础计算树的深度
     3  */
     4 int GetTreeDept(const TNode<T> *t) {
     5     int i, j;
     6     if (t == 0) {
     7         return 0;
     8     } else {
     9         //递归计算左子树的深度
    10         i = this->GetTreeDept(t->lchild);
    11         //递归计算右子树的深度
    12         j = this->GetTreeDept(t->rchild);
    13     }
    14 
    15     //t的深度为其左右子树中深度中的大者加1
    16     return i > j ? i + 1 : j + 1;
    17 }

    5、前序非递归遍历树 

    如下动画flash不知道是网上那位大牛做,在这里借用下,阅读文章的朋友如果有做flash做的比较好,请帮忙指点下我,谢谢

    如下中图详细分析下面代码运行过程

    如下代码

     1 /**
     2  *前序非递归(利用栈)遍历二叉树
     3  *前序遍历的规则:根左右
     4  *非递归遍历树会经常当做面试题,考察面试者的编程能力
     5  *防止下次被鄙视,应该深入理解并且动手在纸写出来
     6  */
     7 void PreOrderTraverse() {
     8     //申明一个栈对象
     9     stack<TNode<T>*> s;
    10     //t首先指向根节点
    11     TNode<T> *t = root;
    12     //压入一个空指针,作为判断条件
    13     s.push(0);
    14 
    15     //如果t所值节点非空
    16     while (t != 0) {
    17         //直接访问根节点
    18         std::cout << (&t->data) << " ";
    19 
    20         //右孩子指针为非空
    21         if (t->rchild != 0) {
    22             //入栈右孩子指针
    23             s.push(t->rchild);
    24         }
    25 
    26         //左孩子指针为非空
    27         if (t->lchild != 0) {
    28             //直接指向其左孩子
    29             t = t->lchild;
    30         } else {//左孩子指针为空
    31             //获取栈顶元素(右孩子指针)
    32             t = s.top();
    33             //清楚栈顶元素
    34             s.pop();
    35         }
    36 
    37     }
    38 }

    6、中序非递归遍历树

    如下动画flash不知道是网上那位大牛做,在这里借用下,阅读文章的朋友如果有做flash做的比较好,请帮忙指点下我,谢谢 

    如下图是代码遍历树的节点顺序,看的不是很明白的朋友,可以像前面先序中那样方式,用图画出每一个步骤,便于跟好的理解

    如下是代码

     1 /**
     2  *中序非递归(利用栈)遍历二叉树
     3  *前序遍历的规则:左根右
     4  */
     5 void InOrderTraverse() {
     6     //申明一个栈对象
     7     stack<TNode<T>*> s;
     8     //t首先指向根节点
     9     TNode<T>* t = root;
    10 
    11     //节点不为空或者栈对象不为空,都进入循环
    12     while (t != 0 || !s.empty()) {
    13         //如果t节点非空
    14         if (t) {
    15             //入栈t节点
    16             s.push(t);
    17             //t节点指向其左孩子
    18             t = t->lchild;
    19         } else {
    20             //获取栈顶元素(左孩子指针)
    21             t = s.top();
    22             //清楚栈顶元素
    23             s.pop();
    24             //直接访问t节点
    25             std::cout << (&t->data) << " ";
    26             //t节点指向其右孩子
    27             t = t->rchild;
    28         }
    29     }
    30 }

    7、后序非递归遍历树

    如下动画flash不知道是网上那位大牛做,在这里借用下,阅读文章的朋友如果有做flash做的比较好,请帮忙指点下我,谢谢  

    如下图是代码遍历树的节点顺序,看的不是很明白的朋友,可以像前面先序中那样方式,用图画出每一个步骤,便于跟好的理解

    如下是代码

     1 /**
     2  *后序非递归(利用栈)遍历二叉树
     3  *前序遍历的规则:左右根
     4  */
     5 void PostOrderTraverse() {
     6     //申明一个栈对象
     7     stack<TNode<T>*> s;
     8     //t首先指向根节点
     9     TNode<T>* t = root;
    10     //申请中间变量,用做判断标识
    11     TNode<T>* r;
    12     //节点不为空或者栈对象不为空,都进入循环
    13     while (t != 0 || !s.empty()) {
    14         //如果t节点非空
    15         if (t) {
    16             //入栈t节点
    17             s.push(t);
    18             //t节点指向其左孩子
    19             t = t->lchild;
    20         } else {
    21             //获取栈顶元素(左孩子指针)
    22             t = s.top();
    23             //判断t的右子树是否存在并且没有访问过
    24             if (t->rchild && t->rchild != r) {
    25                 //t节点指向其右孩子
    26                 t = t->rchild;
    27                 //入栈t节点
    28                 s.push(t);
    29                 //t节点指向其左孩子
    30                 t = t->lchild;
    31             } else {
    32                 //获取栈顶元素(左孩子指针)
    33                 t = s.top();
    34                 //清楚栈顶元素
    35                 s.pop();
    36                 //直接访问t节点
    37                 std::cout << (&t->data) << " ";
    38                 //设置已经访问过的节点,防止多次访问(右孩子指针)
    39                 r = t;
    40                 t = 0;
    41             }
    42         }
    43     }
    44 }

    8、根据模式递归遍历二叉树

     1 /**
     2  * 根据模式递归遍历二叉树
     3  * 下面代码相对比较简单,只要记住遍历树的规则并且弄一点递归,都可以写出来
     4  * 如果在面试中实在写不出来非递归方式,可以写一个递归版本,也许可以争取一个好的工作
     5  */
     6 void OrderTraverse(const TNode<T>* t, Style mode) {
     7     if (t) {
     8         //先序遍历二叉树:根左右
     9         if (mode == Pre) {
    10             //直接访问t节点
    11             std::cout << (&t->data) << " ";
    12             //递归遍历左子树
    13             this->OrderTraverse(t->lchild, mode);
    14             //递归遍历右子树
    15             this->OrderTraverse(t->rchild, mode);
    16         }
    17         //中序遍历二叉树:左根右
    18         if (mode == In) {
    19             //递归遍历左子树
    20             this->OrderTraverse(t->lchild, mode);
    21             //直接访问t节点
    22             std::cout << (&t->data) << " ";
    23             //递归遍历右子树
    24             this->OrderTraverse(t->rchild, mode);
    25         }
    26         //后序遍历二叉树:左右根
    27         if (mode == Post) {
    28             //递归遍历左子树
    29             this->OrderTraverse(t->lchild, mode);
    30             //递归遍历右子树
    31             this->OrderTraverse(t->rchild, mode);
    32             //直接访问t节点
    33             std::cout << (&t->data) << " ";
    34         }
    35     }
    36 }

    9、运行结果,由于在虚拟机中打中文,实在太痛苦,弄一点英文装下B

     测试代码如下:

     1 void test() {
     2 
     3     ifstream fin("data.txt");
     4     this->CreateTreeFromFile(fin);
     5     std::cout << "create tree success" << std::endl;
     6 
     7     std::cout << "create tree after is null ? ";
     8     std::cout << boolalpha << this->IsEmpty();
     9 
    10     std::cout << std::endl;
    11     std::cout << "calculated depth of the tree begins" << std::endl;
    12     std::cout << "tree is dept = " << this->GetTreeDept(this->GetRoot());
    13     std::cout << std::endl;
    14     std::cout << "calculated depth of the tree end" << std::endl;
    15 
    16     std::cout << std::endl;
    17     std::cout << "not recursion--------------------begin" << std::endl;
    18     std::cout << "pre order traverse: ";
    19     this->PreOrderTraverse();
    20     std::cout << std::endl;
    21 
    22     std::cout << "in order traverse: ";
    23     this->InOrderTraverse();
    24     std::cout << std::endl;
    25 
    26     std::cout << "post order traverse: ";
    27     this->PostOrderTraverse();
    28     std::cout << std::endl;
    29     std::cout << "not recursion--------------------end" << std::endl;
    30 
    31     std::cout << std::endl;
    32     std::cout << "recursion--------------------begin" << std::endl;
    33     std::cout << "pre order traverse:";
    34     this->OrderTraverse(this->GetRoot(), Pre);
    35     std::cout << std::endl;
    36 
    37     std::cout << "in order traverse:";
    38     this->OrderTraverse(this->GetRoot(), In);
    39     std::cout << std::endl;
    40 
    41     std::cout << "post order traverse:";
    42     this->OrderTraverse(this->GetRoot(), Post);
    43     std::cout << std::endl;
    44     std::cout << "recursion--------------------end" << std::endl;
    45 }
    View Code

    10、完整代码

    TNode.h 

     1 /*
     2  * TLNode.h
     3  *
     4  *  Created on: 2013-7-6
     5  *      Author: sunysen
     6  */
     7 
     8 #ifndef TLNODE_H_
     9 #define TLNODE_H_
    10 template <class T>
    11 class TNode{
    12 public:
    13     T data;
    14     TNode *rchild,*lchild;
    15     TNode(T value):data(value),rchild(0),lchild(0){}
    16 };
    17 
    18 #endif /* TLNODE_H_ */
    View Code

      LinkTree.h

      1 /*
      2  * LinkTree.h
      3  *  Created on: 2013-7-6
      4  *      Author: sunysen
      5  */
      6 
      7 #ifndef LINKTREE_H_
      8 #define LINKTREE_H_
      9 #include "core/common/Common.h"
     10 #include "core/node/TNode.h"
     11 #include <queue>
     12 #include <stack>
     13 
     14 //树的三种遍历方式
     15 enum Style {
     16     Pre, In, Post
     17 };
     18 
     19 /**
     20  *链式树
     21  */
     22 template<class T>
     23 class LinkTree {
     24 private:
     25     TNode<T> *root;//树的根节点
     26 
     27     /**
     28      *读取文件并赋值给遍历c
     29      */
     30     void InputFromFile(ifstream &f, T &c) {
     31         f >> c;
     32     }
     33 
     34     /**
     35      *根据节点递归清空树
     36      */
     37     void Clear(TNode<T>* t) {
     38         //判断指针是否为空
     39         if (t) {
     40             //获取资源立即放入管理对象(参考Effective C++里边条款13)
     41             //tr1::shared_ptr(引用计数智慧指针)管理对象比auto_ptr更强大
     42             std::auto_ptr<TNode<T> > new_ptr(t);
     43 
     44             //递归清空右子树
     45             Clear(new_ptr->rchild);
     46 
     47             //递归清空左子树
     48             Clear(new_ptr->lchild);
     49         }
     50 
     51         //清空树的根节点
     52         t = 0;
     53     }
     54 public:
     55     /**
     56      * 构造函数初始化树根节点
     57      */
     58     LinkTree() :
     59         root(0) {
     60     }
     61     /**
     62      *析构行数释放所有构造的资源
     63      */
     64     ~LinkTree() {
     65         Clear();
     66     }
     67 
     68     /**
     69      *根据文件内容递归创建树
     70      */
     71     void CreateTreeFromFile(ifstream &f) {
     72         //每次读取一个字符
     73         T e;
     74         InputFromFile(f, e);
     75         if (e == '#') {
     76             return;
     77         }
     78 
     79         //创建一个新的节点
     80         root = new TNode<T> (e);
     81 
     82         //创建左右两个树对象
     83         LinkTree<T> left, right;
     84         //递归创建左子树
     85         left.CreateTreeFromFile(f);
     86         //递归创建右子树
     87         right.CreateTreeFromFile(f);
     88 
     89         //设置根节点的左孩子接左子树的根节点
     90         root->lchild = left.root;
     91         left.root = 0;
     92         //设置根节点的右孩子接右子树的根节点
     93         root->rchild = right.root;
     94         right.root = 0;
     95     }
     96 
     97     /**
     98      * 若树为空,则返回true;否则返回false
     99      */
    100     bool IsEmpty() {
    101         return root == 0;
    102     }
    103     /**
    104      *清空树的所有节点
    105      */
    106     void Clear() {
    107         Clear(root);
    108     }
    109 
    110     /**
    111      *获取const修饰的根节点,相当于做一次类型转换
    112      */
    113     const TNode<T>* GetRoot() {
    114         return root;
    115     }
    116 
    117     /**
    118      * 以传入节点为基础计算树的深度
    119      */
    120     int GetTreeDept(const TNode<T> *t) {
    121         int i, j;
    122         if (t == 0) {
    123             return 0;
    124         } else {
    125             //递归计算左子树的深度
    126             i = this->GetTreeDept(t->lchild);
    127             //递归计算右子树的深度
    128             j = this->GetTreeDept(t->rchild);
    129         }
    130 
    131         //t的深度为其左右子树中深度中的大者加1
    132         return i > j ? i + 1 : j + 1;
    133     }
    134 
    135 
    136     /**
    137      *前序非递归(利用栈)遍历二叉树
    138      *前序遍历的规则:根左右
    139      *非递归遍历树会经常当做面试题,考察面试者的编程能力
    140      *防止下次被鄙视,应该深入理解并且动手在纸写出来
    141      */
    142     void PreOrderTraverse() {
    143         //申明一个栈对象
    144         stack<TNode<T>*> s;
    145         //t首先指向根节点
    146         TNode<T> *t = root;
    147         //压入一个空指针,作为判断条件
    148         s.push(0);
    149 
    150         //如果t所值节点非空
    151         while (t != 0) {
    152             //直接访问根节点
    153             std::cout << (&t->data) << " ";
    154 
    155             //右孩子指针为非空
    156             if (t->rchild != 0) {
    157                 //入栈右孩子指针
    158                 s.push(t->rchild);
    159             }
    160 
    161             //左孩子指针为非空
    162             if (t->lchild != 0) {
    163                 //直接指向其左孩子
    164                 t = t->lchild;
    165             } else {//左孩子指针为空
    166                 //获取栈顶元素(右孩子指针)
    167                 t = s.top();
    168                 //清楚栈顶元素
    169                 s.pop();
    170             }
    171 
    172         }
    173     }
    174 
    175     /**
    176      *中序非递归(利用栈)遍历二叉树
    177      *前序遍历的规则:左根右
    178      */
    179     void InOrderTraverse() {
    180         //申明一个栈对象
    181         stack<TNode<T>*> s;
    182         //t首先指向根节点
    183         TNode<T>* t = root;
    184 
    185         //节点不为空或者栈对象不为空,都进入循环
    186         while (t != 0 || !s.empty()) {
    187             //如果t节点非空
    188             if (t) {
    189                 //入栈t节点
    190                 s.push(t);
    191                 //t节点指向其左孩子
    192                 t = t->lchild;
    193             } else {
    194                 //获取栈顶元素(左孩子指针)
    195                 t = s.top();
    196                 //清楚栈顶元素
    197                 s.pop();
    198                 //直接访问t节点
    199                 std::cout << (&t->data) << " ";
    200                 //t节点指向其右孩子
    201                 t = t->rchild;
    202             }
    203         }
    204     }
    205     /**
    206      *后序非递归(利用栈)遍历二叉树
    207      *前序遍历的规则:左右根
    208      */
    209     void PostOrderTraverse() {
    210         //申明一个栈对象
    211         stack<TNode<T>*> s;
    212         //t首先指向根节点
    213         TNode<T>* t = root;
    214         //申请中间变量,用做判断标识
    215         TNode<T>* r;
    216         //节点不为空或者栈对象不为空,都进入循环
    217         while (t != 0 || !s.empty()) {
    218             //如果t节点非空
    219             if (t) {
    220                 //入栈t节点
    221                 s.push(t);
    222                 //t节点指向其左孩子
    223                 t = t->lchild;
    224             } else {
    225                 //获取栈顶元素(左孩子指针)
    226                 t = s.top();
    227                 //判断t的右子树是否存在并且没有访问过
    228                 if (t->rchild && t->rchild != r) {
    229                     //t节点指向其右孩子
    230                     t = t->rchild;
    231                     //入栈t节点
    232                     s.push(t);
    233                     //t节点指向其左孩子
    234                     t = t->lchild;
    235                 } else {
    236                     //获取栈顶元素(左孩子指针)
    237                     t = s.top();
    238                     //清楚栈顶元素
    239                     s.pop();
    240                     //直接访问t节点
    241                     std::cout << (&t->data) << " ";
    242                     //设置已经访问过的节点,防止多次访问(右孩子指针)
    243                     r = t;
    244                     t = 0;
    245                 }
    246             }
    247         }
    248     }
    249     /**
    250      * 根据模式递归遍历二叉树
    251      * 下面代码相对比较简单,只要记住遍历树的规则并且弄一点递归,都可以写出来
    252      * 如果在面试中实在写不出来非递归方式,可以写一个递归版本,也许可以争取一个好的工作
    253      */
    254     void OrderTraverse(const TNode<T>* t, Style mode) {
    255         if (t) {
    256             //先序遍历二叉树:根左右
    257             if (mode == Pre) {
    258                 //直接访问t节点
    259                 std::cout << (&t->data) << " ";
    260                 //递归遍历左子树
    261                 this->OrderTraverse(t->lchild, mode);
    262                 //递归遍历右子树
    263                 this->OrderTraverse(t->rchild, mode);
    264             }
    265             //中序遍历二叉树:左根右
    266             if (mode == In) {
    267                 //递归遍历左子树
    268                 this->OrderTraverse(t->lchild, mode);
    269                 //直接访问t节点
    270                 std::cout << (&t->data) << " ";
    271                 //递归遍历右子树
    272                 this->OrderTraverse(t->rchild, mode);
    273             }
    274             //后序遍历二叉树:左右根
    275             if (mode == Post) {
    276                 //递归遍历左子树
    277                 this->OrderTraverse(t->lchild, mode);
    278                 //递归遍历右子树
    279                 this->OrderTraverse(t->rchild, mode);
    280                 //直接访问t节点
    281                 std::cout << (&t->data) << " ";
    282             }
    283         }
    284     }
    285 
    286     void test() {
    287 
    288         ifstream fin("data.txt");
    289         this->CreateTreeFromFile(fin);
    290         std::cout << "create tree success" << std::endl;
    291 
    292         std::cout << "create tree after is null ? ";
    293         std::cout << boolalpha << this->IsEmpty();
    294 
    295         std::cout << std::endl;
    296         std::cout << "calculated depth of the tree begins" << std::endl;
    297         std::cout << "tree is dept = " << this->GetTreeDept(this->GetRoot());
    298         std::cout << std::endl;
    299         std::cout << "calculated depth of the tree end" << std::endl;
    300 
    301         std::cout << std::endl;
    302         std::cout << "not recursion--------------------begin" << std::endl;
    303         std::cout << "pre order traverse: ";
    304         this->PreOrderTraverse();
    305         std::cout << std::endl;
    306 
    307         std::cout << "in order traverse: ";
    308         this->InOrderTraverse();
    309         std::cout << std::endl;
    310 
    311         std::cout << "post order traverse: ";
    312         this->PostOrderTraverse();
    313         std::cout << std::endl;
    314         std::cout << "not recursion--------------------end" << std::endl;
    315 
    316         std::cout << std::endl;
    317         std::cout << "recursion--------------------begin" << std::endl;
    318         std::cout << "pre order traverse:";
    319         this->OrderTraverse(this->GetRoot(), Pre);
    320         std::cout << std::endl;
    321 
    322         std::cout << "in order traverse:";
    323         this->OrderTraverse(this->GetRoot(), In);
    324         std::cout << std::endl;
    325 
    326         std::cout << "post order traverse:";
    327         this->OrderTraverse(this->GetRoot(), Post);
    328         std::cout << std::endl;
    329         std::cout << "recursion--------------------end" << std::endl;
    330     }
    331 
    332 };
    333 
    334 #endif /* LINKTREE_H_ */
    View Code

    Common.h 

     1 /*
     2  * Common.h
     3  *
     4  *  Created on: May 17, 2012
     5  *      Author: sunysen
     6  */
     7 
     8 #ifndef COMMON_H_
     9 #define COMMON_H_
    10 
    11 #include <iostream>
    12 #include <fstream>
    13 #include "memory"
    14 #include "string"
    15 #include "string.h"
    16 #include <stdio.h>
    17 #include <stdlib.h>
    18 #include <math.h>
    19 
    20 
    21 using namespace std;
    22 #endif /* COMMON_H_ */
    View Code

    六:环境

    1、运行环境:Ubuntu 10.04 LTS+VMware8.0.4+gcc4.4.3

    2、开发工具:Eclipse+make

    七:题记

    1、上面的代码难免有bug,如果你发现代码写的有问题,请你帮忙指出,让我们一起进步,让代码变的更漂亮和更健壮;

    2、我自己能手动写上面代码,离不开郝斌、高一凡、侯捷、严蔚敏等老师的书籍和视频指导,在这里感谢他们;

    3、鼓励自己能坚持把更多数据结构方面的知识写出来,让自己掌握更深刻,也顺便冒充下"小牛"

     

     

    欢迎继续阅读“启迪思维:数据结构和算法”系列

  • 相关阅读:
    Java -- 最简单的认识重载
    maven打包spring boot项目及跳过test文件
    springboot 配置elasticsearch Java High Rest Client
    面向对象与面向过程的区别
    vue --- axios拦截器+form格式请求体
    kotlin --- 时间戳与字符串互相转换
    各种技术的路线图
    bpmn-js起步
    纵观 jBPM:从 jBPM3 到 jBPM5 以及 Activiti5
    几大工作流引擎对比
  • 原文地址:https://www.cnblogs.com/sunysen/p/3201503.html
Copyright © 2020-2023  润新知