写了点函数库,刷题用
实现二叉树基本数据结构和基本操作:
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;
}