我的coding练习

我的coding练习

二叉树

L、D、R分别表示遍历左子树、访问根结点和遍历右子树

  • 深度优先遍历:

    • 先(前)序遍历:DLR : 只是为了遍历
    • 中序遍历:LDR : 顺序输出
    • 后序遍历:LRD : 适合破坏性操作(delete等)
  • 广度优先遍历:

    • 层序遍历

仅有前序和后序遍历,不能确定一个二叉树,必须有中序遍历的结果

遍历

树节点

struct BTN{
    int data_;
    BTN* left_;
    BTN* right_;
};

前序遍历:DLR

  • 递归
void preOrderTraverse(BTN* p){
    if(p == nullptr){
        return;
    }
    print p->data_;
    preOrderTraverse(p->left_);
    preOrderTraverse(p->right_);
}
  • 非递归
void preOrderTraverse(BTN* p){
    if(p == nullptr){
        return;
    }
    std::stack<BTN*> stack;
    stack.push(p);
    while(!stack.empty()){
        p = stack.top();
        stack.pop();
        print(p->data_);
        if(p->right_){
            stack.push(p->right_);
        }
        if(p->left_){
            stack.push(p->left_);
        }
    }
}

中序遍历:LDR

  • 递归
void preOrderTraverse(BTN* p){
    if(p == nullptr){
        return;
    }
    preOrderTraverse(p->left_);
    print p->data_;
    preOrderTraverse(p->right_);
}
  • 非递归
void inOrderTraverse(BTN* p){
    std::stack<BTN*> stack;
    while(p || !stack.empty()){
        if(p){
            stack.push(p);
            p = p->left_;
        }else{
            p = stack.top();
            stack.pop();
            print(p->data_);
            p = p->right_;
        }
    }
}

后序遍历:DLR

  • 递归
void preOrderTraverse(BTN* p){
    if(p == nullptr){
        return;
    }
    preOrderTraverse(p->right_);
    preOrderTraverse(p->left_);
    print p->data_;
}
  • 非递归
struct TmpBTN{
    BTN* p_;
    bool visited_;
    TmpBTN(BTN* p):p_(p),visited_(false){}
};

void postorderTraversalNew(BTN *p)
{
    std::stack< TmpBTN > s;
    TmpBTN tmpBTN(p);
    s.push(tmpBTN);
    while(!s.empty())
    {
        tmpBTN = s.top();
        s.pop();
        if(tmpBTN.p_ == NULL)
            continue;
        if(tmpBTN.visited_)
        {
            print(tmpBTN.p_->data_);
        }else{
            //可以变换顺序为其他遍历
            tmpBTN.visited_=true;
            s.push(tmpBTN);
            s.push(TmpBTN(tmpBTN.p_->right_));
            s.push(TmpBTN(tmpBTN.p_->left_));
        }
    }
}

层序遍历:

void LevelOrderTraversal(BTN *p){
    std::queue<BTN*> q;
    q.push(p);
    while(!q.empty()){
        p = q.front();
        q.pop();
        if(p){
            print(p->data_);
            q.push(p->left_);
            q.push(p->right_);
        }
    }
}

实现stack和queue:

简单版本: List实现
template<class T>
struct Node{
    T data_;
    Node* next_;
    Node():next_(nullptr){}
    Node(const T& data):data_(data),next_(nullptr){}
};
template<T>
class Stack{
public:
    Stack():head_(nullptr){}
    ~Stack(){
        while(head_){
            Node<T>* toFreeNode = head_;
            head_ = head_->next_;
            delete toFreeNode;
        }
    }
    bool empty(){
        return head_ == nullptr;
    }
    void push(const T& data){
        try{
            Node<T>* newHead = new Node<T>(data);
            newHead->next_=head_;
            head_=newHead;
        }catch(std::bad_alloc& exception){
            throw exception;
        }
    }
    void pop(){
        if(empty()){
            //TODO execption 
        }else{
            Node<T>* toFreeNode = head_;
            head_ = head_->next_;
            delete toFreeNode;
        }
    }
    T top(){
        if(!empty()){
            return head_->data_;
        }else{
            //TODO execption 
        }
    }
private:
    Node<T>* head_;
};
//如果是queue就增加一个Node<T>* tail_;
优化版本: vector实现
  • 注意扩容与copy
template<class T>
class Queue{
public:
    Queue(uint32_t max_size):
        datas_(0),
        max_size_(max_size),
        size_(0),
        head_(0),
        tail_(0){
            datas_ = new T[max_size_];
        }
    ~Queue(){
        delete[] datas_;
    }
    bool empty(){
        return size_ == 0;
    }
    //TODO!
    void push(const T& data){
        if(size_ == max_size_){
            std::cout << "push:" << data << " failed !" << std::endl;
            return;
        }
        datas_[tail_] = data;
        Move(tail_);
        ++size_;
    }
    void pop(){
        if(empty()){
            std::cout << "pop: failed !" << std::endl;
        }else{
            Move(head_);
            --size_;
        }
    }
    T top(){
        if(!empty()){
            return datas_[head_];
        }else{
            std::cout << "top: failed !" << std::endl;
            return T();
        }
    }
private:
    T* datas_;
    uint32_t  max_size_;
    uint32_t  size_;
    int32_t head_;
    int32_t tail_;
    void Move(int32_t& cur){
        if(cur+1 < max_size_){
            ++cur;
        }else{
            cur = 0;
        }
    }
};

对于stackqueue的实现在STL中都是使用deque完成的,内存分段分配结构有点复杂,后续再分析。

queue是一种“先进先出”的数据结构,可以对两端进行操作,但是只能在队列头部进行移除元素,只能在队列尾部新增元素,可以访问队列尾部和头部的元素,但是不能遍历容器,所以queue不需要设计自己的容器。在SGI STL的源码<stl_queue.h>的class queue设计中,它是基于某种容器作为底部结构的,默认容器是deque容器,用户也可以自己指定容器的类型。
queue可以以deque和list作为底层的容器

单元测试:

struct BTN{
    int data_;
    BTN* left_;
    BTN* right_;
    BTN(int data):
        data_(data),
        left_(nullptr),
        right_(nullptr){}
};
//         4  
//    2       6
//  1   3       7

BTN* createBTN(){
    BTN* root = new BTN(4);
    root->left_ = new BTN(2);
    root->left_->left_ = new BTN(1);
    root->left_->right_= new BTN(3);
    root->right_ = new BTN(6);
    root->right_->right_ = new BTN(7);
    return root;
}

void print(int data){
    std::cout << data << std::endl;
}

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335