最近看完了侯捷的STL源码剖析,自己写个案例练练手
这是一个二叉树的容器,参照stl容器
主要实现以下功能:
1.构造函数:可通过两种方式构造
(1)空构造;(2)设置原生指针或容器的头尾指针/迭代器将其填充,第三个参数为空位符,在树中表示NULL;
2.插入函数:
提供左插入insert_left与右插入insert_right,当对应位置已有节点时将该点作为插入点的子节点,第三个参数设置该子节点为其左子/右子,默认为左子,设0则为右子;
3.擦除函数:
提供节点删除erase与枝删除erasebranch,其中节点删除仅适用于子节点<=1的情况,删除节点后由子节点接替其位置。
枝删除通过后序遍历依次将节点释放。
4.遍历方式:
提供4种遍历模式:①层序遍历levelOrder②前序遍历preorderTraversal③中序遍历inorderTraversal④后序遍历postorderTraversal
第一个参数为遍历的起始节点,第二个为仿函数接口,即遍历过程中要完成的动作。其中层序遍历的仿函数需两个参数,第一个相邻层间过渡的标志,过渡时为1。另一个参数为节点的数值。
5.查找函数find:
第一个参数为需查找的数值,第二个参数为起始节点。返回其迭代器。
6.旋转函数:
提供左旋rotate_left与右旋函数rotate_right,即平衡二叉树中常用的旋转操作。
7.迭代器iterator:
通过迭代器来访问二叉树的节点,可实现节点的移动与访问
(1)移动:++往下,–往上,可通过iter_left,iter_right,选择向下的方向(往左/往右)。
(2)访问:重载与->,可通过访问节点数值,->可访问节点成员变量。
上述功能均通过了简单的测试,但时间有限,还没在实际案例中应用,后续根据需要继续完善功能
代码如下:
//踏梦远行——2020.8.1
#include<iostream>
#include<vector>
#include<queue>
#include<list>
#include<sstream>
using namespace std;
template<class T>
struct treenode
{
typedef treenode<T>* pointer;
T data;
pointer left;
pointer right;
pointer parent;
};
//-------------------------
template<class T>
class treeiter
{
public:
typedef treenode<T>* pointer;
treeiter() :itertype(0) {};
treeiter(pointer n) :node(n),itertype(0) {};
void operator=(pointer n) { node = n; itertype = 0; };
pointer operator++(int);
pointer& operator++();
pointer operator--(int);
pointer& operator--();
bool operator==(pointer p)const {return this->node == p;};
T operator *()const { return node->data; };
typename treeiter<T>::pointer operator ->() { return node; };
void iter_left() { itertype = 0; };
void iter_right() { itertype = 1; };
pointer node;
private:
unsigned char itertype;
};
template<class T>
typename treeiter<T>::pointer treeiter<T>::operator++(int)
{
pointer tmp = node;
switch (itertype) {
case 0:node = node->left;
break;
case 1:node = node->right;
break;
default:
break;
}
return tmp;
}
template<class T>
typename treeiter<T>::pointer& treeiter<T>::operator++()
{
switch (itertype) {
case 0:node = node->left;
break;
case 1:node = node->right;
break;
default:
break;
}
return node;
}
template<class T>
typename treeiter<T>::pointer treeiter<T>::operator--(int)
{
pointer tmp = node;
node = node->parent;
return tmp;
}
template<class T>
typename treeiter<T>::pointer& treeiter<T>::operator--()
{
node = node->parent;
return node;
}
//-------------------------
template<class T>
class mytree
{
public:
typedef treenode<T> value;
typedef treenode<T>* pointer;
typedef treeiter<T> iterator;
mytree();
template<class U>
mytree(U l, U r, T sign);
iterator gethead() { return head; }
iterator begin() { return head->left; }
iterator end() { return NULL; }
void insert_left(treeiter<T> parent, T x, bool left = 1);
void insert_right(treeiter<T> parent, T x, bool left = 1);
void erase(treeiter<T> parent);
void erasebranch(treeiter<T> parent);
template<class func>
void levelOrder(iterator pos, func& fun);
template<class func>
void preorderTraversal(iterator pos,func& fun);
template<class func>
void inorderTraversal(iterator pos, func& fun);
template<class func>
void postorderTraversal(iterator pos, func& fun);
iterator find(T pos, iterator start);
void rotate_left(iterator start);
void rotate_right(iterator start);
private:
pointer head;
pointer node;
template<class U>
void constuctree(U l, U r, T sign, random_access_iterator_tag);
template<class U>
void constuctree(U l, U r, T sign, input_iterator_tag);
pointer createnode() { return new value; }
void erasebranch_base(iterator parent);
};
template<class T>
mytree<T>::mytree() {
head = new value;
head->left = NULL;
head->right = NULL;
head->parent = NULL;
node = head;
};
template<class T>
template<class U>
mytree<T>::mytree(U l, U r,T sign) {
constuctree( l, r,sign,iterator_traits<U>::iterator_category());
};
template<class T>
template<class U>
void mytree<T>::constuctree(U l, U r, T sign,random_access_iterator_tag)
{
head = new value;
head->left = NULL;
head->right = NULL;
head->parent = NULL;
node = head;
if (l <= r)
{
U pos = l;
treeiter<T> it = head;
int n = r - l - 1;
insert_left(it, *pos++);
queue<pointer> myq;
myq.push(begin());
while (n > 0)
{
it = myq.front();
myq.pop();
if (*pos!=sign) {
insert_left(it, *pos);
myq.push(it->left);
}
pos++;
if (!--n)break;
if (*pos!=sign) {
insert_right(it, *pos);
myq.push(it->right);
}
pos++;
--n;
}
}
}
template<class T>
template<class U>
void mytree<T>::constuctree(U l, U r, T sign,input_iterator_tag)
{
head = new value;
head->left = NULL;
head->right = NULL;
head->parent = NULL;
node = head;
U pos = l;
treeiter<T> it = head;
insert_left(it, *pos++);
queue<pointer> myq;
myq.push(head->left);
while (pos !=r)
{
it = myq.front();
myq.pop();
if (*pos!=sign) {
insert_left(it, *pos);
myq.push(it->left);
}
pos++;
if (pos==r)break;
if (*pos!=sign) {
insert_right(it, *pos);
myq.push(it->right);
}
pos++;
}
}
template<class T>
void mytree<T>::insert_left(treeiter<T> parent, T x, bool left)
{
node = createnode();
node->parent = parent.node;
node->data = x;
if (left)node->left = parent.node->left;
else node->right = parent.node->left;
node->right = NULL;
parent.node->left = node;
}
template<class T>
void mytree<T>::insert_right(treeiter<T> parent, T x, bool left) {
node = createnode();
node->parent = parent.node;
node->data = x;
if (left)node->left = parent.node->right;
else node->right = parent.node->right;
node->right = NULL;
parent.node->right = node;
}
template<class T>
void mytree<T>::erase(treeiter<T> parent)
{
if (!parent->left && !parent->right) {
if (parent == parent->parent->left)parent->parent->left = NULL;
else parent->parent->right = NULL;
delete parent.node;
return;
}
if (!parent->left){
if (parent->parent->left == parent.node) parent->parent->left = parent->right;
else parent->parent->right = parent->right;
parent->right->parent = parent->parent;
delete parent.node;
return;
}
if (!parent->right) {
if (parent->parent->left == parent.node) parent->parent->left = parent->left;
else parent->parent->right = parent->left;
parent->left->parent = parent->parent;
delete parent.node;
return;
}
}
template<class T>
void mytree<T>::erasebranch(iterator parent)
{
if (parent == parent->parent->left)parent->parent->left = NULL;
else parent->parent->right = NULL;
erasebranch_base(parent);
}
template<class T>
void mytree<T>::erasebranch_base(iterator parent)
{
if (!parent.node) return;
erasebranch_base(parent->left); //后序遍历
erasebranch_base(parent->right);
delete parent.node;
}
template<class T>
template<class func>
void mytree<T>::levelOrder(mytree<T>::iterator pos,func& fun) {
if (!pos.node)return;
pointer temp;
queue<pointer> myq;
myq.push(pos.node);
int len;
while (!myq.empty())
{
len = myq.size();
for (int i = 0; i < len; i++)
{
temp = myq.front();
myq.pop();
fun(!i,temp->data);
if (temp->left)myq.push(temp->left);
if (temp->right)myq.push(temp->right);
}
}
}
template<class T>
template<class func>
void mytree<T>::preorderTraversal(mytree<T>::iterator pos,func& fun) {
if (!pos.node) return;
fun(pos->data);
preorderTraversal(pos->left,fun);
preorderTraversal(pos->right,fun);
}
template<class T>
template<class func>
void mytree<T>::inorderTraversal(mytree<T>::iterator pos, func& fun) {
if (!pos.node) return;
inorderTraversal(pos->left,fun);
fun(pos->data);
inorderTraversal(pos->right,fun);
}
template<class T>
template<class func>
void mytree<T>::postorderTraversal(mytree<T>::iterator pos, func& fun) {
if (!pos.node) return;
postorderTraversal(pos->left, fun);
postorderTraversal(pos->right, fun);
fun(pos->data);
}
template<class T>
typename mytree<T>::iterator mytree<T>::find(T pos, mytree<T>::iterator start)
{
if (!start.node)return NULL;
if (start->data == pos)return start;
if (find(pos, start->left).node)return find(pos, iterator(start->left));
if (find(pos, start->right).node)return find(pos, iterator(start->right));
return NULL;
}
template<class T>
void mytree<T>::rotate_left(mytree<T>::iterator start)
{
if (!start->right)return;
if (start == start->parent->right)start->parent->right = start->right;
else start->parent->left = start->right;
start->right->parent = start->parent;
start->parent = start->right;
start->right = start->parent->left;
start->parent->left = start.node;
if(start->right)start->right->parent = start.node;
start = start->parent;
}
template<class T>
void mytree<T>::rotate_right(mytree<T>::iterator start)
{
if (!start->left)return;
if (start == start->parent->right)start->parent->right = start->left;
else start->parent->left = start->left;
start->left->parent = start->parent;
start->parent = start->left;
start->left = start->parent->right;
start->parent->right = start.node;
if (start->left)start->left->parent = start.node;
start = start->parent;
}
//-------------------------
template<class T>
void show(vector<vector<T>> v)
{
for (int i = 0; i < v.size(); i++)
{
for (int j = 0; j < v[i].size()-1; j++)
cout << v[i][j]<<"| |";
cout << v[i][v[i].size()-1]<<endl;
}
}
template<class T>
void show(vector<T> v)
{
for (int i = 0; i < v.size()-1; i++)
{
cout << v[i] << "| |";
}
cout << v[v.size() - 1] << endl;
}
class savevec
{
public:
vector<double> v;
void operator()(double x)
{
v.push_back(x);
}
~savevec() { v.clear(); };
};
class savevvec
{
public:
vector<vector<double>> v;
void operator()(int sign,double x)
{
if (sign)(v.push_back({}));
v.back().push_back(x);
}
~savevvec() { v.clear(); };
};
int main()
{
double arr[] = { 1,5,6,8,9,7,3,0,9,10 };
list<double> l(arr, arr + 10);
mytree<double> t(l.begin(),l.end(),0);
//treeiter<double> it = t.gethead();
//t.insert_left(it, 5);
//it.iter_left();
//it++;
//t.insert_left(it, 4.7);
//t.insert_right(it, 10.5);
//t.insert_right(it, 9);
//it--;
//t.insert_left(it, 8);
mytree<double>::iterator it = t.begin();
savevvec savv;
t.levelOrder(it,savv);
show(savv.v);
cout << "----------" << endl;
savevec sav;
t.preorderTraversal(it,sav);
show(sav.v);
sav.v.clear();
t.erase(t.find(8, t.begin()));
t.inorderTraversal(it,sav);
show(sav.v);
sav.v.clear();
t.erasebranch(t.find(6, t.begin()));
t.postorderTraversal(it,sav);
show(sav.v);
sav.v.clear();
it=t.find(5, t.begin());
t.rotate_right(it);
system("pause");
}