【Coding】写的一点车轮子,有关树和数组的

写了点函数库,刷题用

实现二叉树基本数据结构和基本操作:

BiTree.h

//
// Created by Arylise on 2021/4/5.
//

#ifndef CODING_BITREE_H
#define CODING_BITREE_H

#include <vector>
#include <queue>
#include <iostream>

using namespace std;

///在调用的文件要先define所需类型,针对以下的关键字来确定所创建的树的val类型

#ifdef _INT
#define K int
K endOfInput = -1;/// 表示树的输入结尾
#undef _INT
#endif

#ifdef _LONG
#define K long long
K endOfInput = -1;
#undef _LONG
#endif

#ifdef _DOUBLE
#define K double
K endOfInput = 0.0;
#undef _DOUBLE
#endif

#ifdef _CHAR
#define K char
K endOfInput = '%';
#undef _CHAR
#endif


struct TreeNode {///TreeNode结构体
    K val;
    struct TreeNode *left;
    struct TreeNode *right;

    TreeNode() : left(nullptr), val(0), right(nullptr) {}

    TreeNode(K x) : left(nullptr), val(x), right(nullptr) {}

    TreeNode(TreeNode *left, K x) : left(left), val(x), right(nullptr) {}

    TreeNode(K x, TreeNode *right) : left(nullptr), val(x), right(right) {}

    TreeNode(TreeNode *left, K x, TreeNode *right) : left(left), val(x), right(right) {}
};

class BiTree {/// BiTree类

private:
    vector<K> innerList;/// innerList是数组化的树
    int valCounter = 0;

private:
    void _input() {///初始化树的数组
        K input;
        cin >> input;
        while (input != endOfInput) {
            innerList.push_back(input);
            cin >> input;
        }
    }

    K _getVal() {///从树的数组中取出元素给树赋值
        if (valCounter < innerList.size()) {
            return innerList[valCounter++];
        }
        return endOfLeaf;
    }

    TreeNode *_creatNode() {///生成节点
        K i = _getVal();
        if (i == endOfLeaf) {
            return nullptr;
        }
        return new TreeNode(i);
    }

    /**
     * initFun
     */
    void _creatTreeByLevel() {///层序输入一棵树,当然先徐工后序中序没写,需要的话以后补上把,反正也就几个递归的事
        if (!(root = _creatNode())) {
            return;
        }
        queue<TreeNode *> sta;
        sta.push(root);
        while (!sta.empty()) {
            TreeNode *p = sta.front();
            sta.pop();
            if ((p->left = _creatNode())) {
                sta.push(p->left);
            }
            if ((p->right = _creatNode())) {
                sta.push(p->right);
            }
        }
    }


    /**
     * oderFunc
     * @param node
     */
    static  void _preOder(TreeNode *node) {
        if (node) {
            cout << node->val << " ";
            _preOder(node->left);
            _preOder(node->right);
        } else
            cout << endOfLeaf << " ";
    }

    static void _inOder(TreeNode *node) {
        if (node) {
            _inOder(node->left);
            cout << node->val << " ";
            _inOder(node->right);
        } else
            cout << endOfLeaf << " ";
    }

    static void _postOder(TreeNode *node) {
        if (node) {
            _postOder(node->left);
            _postOder(node->right);
            cout << node->val << " ";
        } else
            cout << endOfLeaf << " ";
    }


    static void _levelOder(TreeNode *node) {
        queue<TreeNode *> sta;
        sta.push(node);
        while (!sta.empty()) {
            if (sta.front()) {
                TreeNode *p = sta.front();
                cout << p->val << " ";
                if (p->left) {
                    sta.push(p->left);
                } else {
                    sta.push(nullptr);
                }
                if (p->right) {
                    sta.push(p->right);
                } else {
                    sta.push(nullptr);
                }
            } else {
                cout << endOfLeaf << " ";
            }
            sta.pop();
        }
    }


public:
    static char endOfLeaf;

    TreeNode *root;

    enum WriteType {///enum是为了方便确定树的生成类型,在构造其中确认具体什么类型,默认为层序输入,如果想自己写输入方式,就在后面加就行,在重写的构造器加上所对应的case
        ByLevel
    };

    enum Oder {///这个enum是为了方便sort确定遍历类型,默认是层序,需要就直接sort()里加枚举指定就行
        PreOder, InOder, PostOder, LevelOder
    };
public:
    BiTree() {
        _input();
        _creatTreeByLevel();
    }

    BiTree(WriteType type) {///重写的构造器方便指定输入类型
        _input();
        switch (type) {
            case ByLevel :

                _creatTreeByLevel();

                break;
        }
    }

public:
    BiTree *show() {///写成BiTree*类型是为了方便链式引用
        _levelOder(root);
        cout << endl;
        return this;
    }

    BiTree *show(Oder oder) {///重写的sort方便指定遍历类型
        switch (oder) {
            case PreOder:
                _preOder(root);
                break;
            case InOder:
                _inOder(root);
                break;
            case PostOder:
                _postOder(root);
                break;
            case LevelOder:
                _levelOder(root);
                break;
        }
        cout << endl;
        return this;
    }

/**
 * 释放内存
 */
    void end() {///最后别忘了加end
        freeTree(root);
        free(this);
    }

/**
 * endFun
 * @param node
 */
    BiTree *freeTree(TreeNode *node) {
        if (node) {
            freeTree(node->left);
            freeTree(node->right);
            free(node);
        }
        return this;
    }
};

char BiTree::endOfLeaf='#';///这个是初始化叶子结点,默认是#代表叶子结点(空)

#undef K
#endif //CODING_BITREE_H


实现链表基本数据结构和基本操作,链表和树的差不多,就不细写注释了

LinkedList.h

//
// Created by Arylise on 2021/4/5.
//

#ifndef CODING_LINKEDLIST_H
#define CODING_LINKEDLIST_H

using namespace std;

#ifdef _INT
#define K int
    K endOfInput = -1;
#undef _INT
#endif

#ifdef _LONG
#define K long long
    K endOfInput = -1;
#undef _LONG
#endif

#ifdef _DOUBLE
#define K double
    K endOfInput = 0.0;
#undef _DOUBLE
#endif

#ifdef _CHAR
#define K char
    K endOfInput = '%';
#undef _CHAR
#endif


struct LinkedNode {
    K val;
    LinkedNode *next;

    LinkedNode(K x) : val(x), next(nullptr) {}

    LinkedNode(K x, LinkedNode *p) : val(x), next(p) {}
};

class LinkedList {

private:
    vector<K> innerList;

    void _input() {
        K input;
        cin >> input;
        while (input != endOfInput) {
            innerList.push_back(input);
            cin >> input;
        }
    }

    K _getVal() {
        if (valCounter < innerList.size()) {
            return innerList[valCounter++];
        }
        return endOfInput;
    }

    LinkedNode *_creatNode(LinkedNode *next) {
        K i = _getVal();
        if (i == endOfInput) {
            return nullptr;
        }
        return new LinkedNode(i, next);
    }

    void _creatListByTail() {
        head = _creatNode(nullptr);
        if (!head) {
            return;
        }
        LinkedNode *node = head;
        while ((node->next = _creatNode(nullptr))) {
            node = node->next;
        }
    }

    void _creatListByHead() {
        head = _creatNode(nullptr);
        if (!head) {
            return;
        }
        LinkedNode *node;
        while ((node = _creatNode(head))) {
            head = node;
        }
    }



    static void _listOder(LinkedNode *node) {
        while (node) {
            cout << node->val << " ";
            node = node->next;
        }
    }

    static LinkedNode *_mergeSort(LinkedNode *node) {
        if (node->next == nullptr) {
            return node;
        }
        /// 快慢指针跑一圈,这样慢指针指向中点
        LinkedNode *fast, *slow;
        fast = slow = node;
        while (fast->next && fast->next->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        /// 分割链表,快指针没用了作为分割链表的头结点
        fast = slow->next;
        slow->next = nullptr;
        /// 分治处理
        slow = _mergeSort(node);
        fast = _mergeSort(fast);
        /// 假设之前已经排好了两个子链表
        /// 排序两条链表的第一个值,作为node返回,node必须接受fast或slow,否则如果node在merge中改动就失去了头结点位置
        if (_cmp(fast, slow)) {
            node = fast;
            fast = fast->next;
        } else {
            node = slow;
            slow = slow->next;
        }
        /// tail作为操作位进行主链表构建
        LinkedNode *tail = node;
        while (fast && slow) {
            ///每次取_cmp设定的比较器
            if (_cmp(fast, slow)) {
                tail->next = fast;
                fast = fast->next;
            } else {
                tail->next = slow;
                slow = slow->next;
            }
            tail = tail->next;/// 别忘了tail要++
        }
        /// 尾部的链表直接对接
        if (fast) {
            tail->next = fast;
        }
        if (slow) {
            tail->next = slow;
        }
        return node;
    }

    static bool _cmp(LinkedNode *a, LinkedNode *b) { return a->val < b->val; }


public:
    LinkedNode *head = nullptr;
     int valCounter=0;
    enum WriteType {
        ByTail, ByHead
    };

    LinkedList() {
        _input();
        _creatListByTail();
    }

    LinkedList(WriteType type) {
        _input();
        switch (type) {
            case ByHead:
                _creatListByHead();
                break;
            case ByTail:
                _creatListByTail();
                break;
        }
    }

    LinkedList *sort() {
        if (head)
            head = _mergeSort(head);
        return this;
    }

    LinkedList *show() {
        _listOder(head);
        cout << endl;
        return this;
    }

    void end() {
        freeNode(head);
        free(this);
    }

    static void freeNode(LinkedNode *node) {
        if (node) {
            freeNode(node);
        }
        free(node);
    }
};
#undef K
#endif //CODING_LINKEDLIST_H

目的是为了方便使用,所以只要再按照我的格式创建.h文件就能直接写算法了给个例子:
使用示例:

FixTree.h

//
// Created by Arylise on 2021/4/11.
//
/**
 * 修剪一棵树为完美二叉树
 * @param tree 
 * @return 
 */
#ifndef CODING_FIXTREE_H
#define CODING_FIXTREE_H
#define _INT///这个_INT制定了里面树的val是什么类型,也可以指定_LONG,_DOUBLE,_CHAR等等,也能自己写类往里填,看需求
#include "../base/BiTree.h"
#undef _INT

BiTree *fixTree(BiTree *tree) {
    /// 特殊情况考虑
    TreeNode *root = tree->root;
    if (root == nullptr) {
        return tree;
    }
    if (root->right == nullptr) {
        BiTree::freeTree(root->left);
        root->left = nullptr;
        return tree;
    }
    if (root->left == nullptr) {
        BiTree::freeTree(root->right);
        root->right = nullptr;
        return tree;
    }

    /// num作为记录本层有多少节点
    int num = 1;
    /// que用来层序遍历树
    queue<TreeNode *> que;
    /// lastLine用来记录上一层节点
    queue<TreeNode *> lastLine;
    /// topLast用来记录下一层的结尾
    TreeNode *nextLast = root->right;
    que.push(root);
    /// 当第一次子树有空,则认为上一层为完全二叉树最后一层,进行修剪
    while (que.front()->left != nullptr && que.front()->right != nullptr) {
//            cout << que.front()->val << endl;
//            cout << que.front()->left->val << " " << que.front()->right->val << endl;

        /// 检测是否为一层的最后一个节点
        if (que.front() == nextLast) {
            /// lastLine去除上一层的节点
            for (int i = 0; i < num; ++i) {
                lastLine.pop();
            }
            /// num*2
            num = num << 1;
            /// 重新记录nextLast
            nextLast = que.front()->right;
        }
        /// 节点塞进记录栈,将子节点压入栈,节点出栈
        lastLine.push(que.front());
        que.push(que.front()->left);
        que.push(que.front()->right);
        que.pop();
//            cout<<"?"<<que.size()<<"?"<<lastLine.size()<<endl;
    }
    /// 以上一层进行修剪,所记录的最后一层不要修剪,会报错(已经被修剪过)
    while (num--) {
        TreeNode *p = lastLine.front();
        BiTree::freeTree(p->left->left);
        BiTree::freeTree(p->left->right);
        BiTree::freeTree(p->right->left);
        BiTree::freeTree(p->right->right);
        p->left->left = nullptr;
        p->left->right = nullptr;
        p->right->left = nullptr;
        p->right->right = nullptr;
        lastLine.pop();
    }
    return tree;
}
#endif //CODING_FIXTREE_H

主函数调用:(这样就能完全链式调用,就很爽)

main.cpp

#include "coding/myCoding/FixTree.h"

using namespace std;

int main() {
    fixTree((new BiTree())->show())
            ->show()->end();
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值