1.Set的简单实现
set是利用二叉查找树来实现的,而且为了查找方便,添加了另外两个指针,一个指向下一个最小结点,一个指向上一个最大结点。
iset.h
//利用二叉查找树实现set #ifndef ISET_H #define ISET_H template<class T> struct Node{ T data; Node<T> *rchild, *lchild; //左右孩子 Node<T> *parent; //父结点 Node<T> *next, *pre; //下一个最小和上一个最大的结点 Node(){ rchild = lchild = parent = 0; next = pre = 0; } }; template<class T> class ISet{ public: ISet(); ISet(T a[], int n); ~ISet(); int size(); bool isEmpty(); bool contains(T t); T* toArray(); void add(T t); void remove(T t); void addAll(T a[], int n); void removeAll(); void clear(); void print(); //下面实现迭代器 typedef Node<T>* iterator; typedef const Node<T>* const_iterator; iterator Iterator(); const_iterator Iterator() const; iterator next(); const_iterator next() const; iterator pre(); const_iterator pre() const; bool hasNext(); bool hasPre(); //还可以操作符重载,++,--,+实现通用的迭代器 private: Node<T>* root; Node<T> *head, *tail; //头(最小)和尾(最大) void clear(Node<T>* &root); int size(Node<T>* root); void print(Node<T>* root); void toArray(Node<T>* root, T* &a, int *i); void deleteNode(Node<T>* &root, Node<T>* r, Node<T>* pre);//删除结点p void preSet(Node<T>* t); void nextSet(Node<T>* t); }; #endif
iset.cpp
#include <iostream> #include "iset.h" using namespace std; template<class T> ISet<T>::ISet(){ head = tail = root = NULL; } template<class T> ISet<T>::ISet(T a[], int n){ head = tail = root = NULL; addAll(a, n); } template<class T> ISet<T>::~ISet(){ clear(); } template<class T> int ISet<T>::size(){ return size(root); } template<class T> bool ISet<T>::isEmpty(){ if(!root) return true; return false; } template<class T> bool ISet<T>::contains(T t){ Node<T>* r = root; while(r){ if(r->data == t) break; r = (r->data > t)?r->lchild:r->rchild; } //如果没找到,返回false if(!r) return false; return true; } template<class T> T* ISet<T>::toArray(){ T *a = new T[size()]; int i = 0; toArray(root, a, &i); return a; } template<class T> void ISet<T>::add(T x){ Node<T>* r = root, *m = NULL, *n = NULL; if(r == NULL){ Node<T>* t = new Node<T>; t->data = x; root = t;//必须设置新的root结点,因为t和root在内存指向位置不同 }else{ Node<T>* p = r; //查找待插入结点位置 while(r){ if(r->data == x){ return; } p = r; if(r->data > x){ n = r; r = r->lchild; }else{ m = r; r = r->rchild; } } Node<T>* t = new Node<T>; t->data = x; if(p->data > x){//插入左 p->lchild = t; p->pre = t; }else{ p->rchild = t; p->next = t; } t->parent = p; preSet(t); nextSet(t); if(m && m!=p) nextSet(m); if(n && n!=p) preSet(n); } } template<class T> void ISet<T>::remove(T x){ if(!root) return; Node<T>* pre = NULL, *r = root; //查找待删除结点位置(pre是r的前序结点) while(r){ if(r->data == x){ break; } pre = r; r = (r->data > x)?r->lchild:r->rchild; } //没找到 if(!r){ cout<<"没有待删除的值:"<<x<<endl; return;} //如果pre == NULL说明是root结点 deleteNode(root, r, pre); } template<class T> void ISet<T>::addAll(T a[], int n){ if(n <= 0) return; for(int i=0; i<n; i++){ add(a[i]); } } template<class T> void ISet<T>::removeAll(){ clear(); } template<class T> void ISet<T>::clear(){ clear(root); //注:当clear之后,root也被delete,故而重新置为NULL root = NULL; } template<class T> void ISet<T>::print(){ print(root); } template<class T> void ISet<T>::print(Node<T>* root){ if(root){ cout<<root->data<<" "; print(root->lchild); print(root->rchild); } } template<class T> void ISet<T>::clear(Node<T>* &root){ if(root){ clear(root->lchild); clear(root->rchild); delete root; } } template<class T> int ISet<T>::size(Node<T>* root){ if(!root) return 0; else{ return size(root->lchild)+size(root->rchild)+1; } } template<class T> void ISet<T>::toArray(Node<T>* root, T* &a, int *i){ if(root){ a[(*i)++] = root->data; toArray(root->lchild, a, i); toArray(root->rchild, a, i); } } //r为待删除结点,pre为r的双亲 template<class T> void ISet<T>::deleteNode(Node<T>* &root, Node<T>* r, Node<T>* pre){ Node<T>* p; //先修改待删除r的pre,next结点指针 if(r->pre){ r->pre->next = r->next; } if(r->next){ r->next->pre = r->pre; } if(!r->rchild && !r->lchild){ //如果是叶子结点 if(pre){ if(pre->lchild == r){ pre->lchild = NULL; }else{ pre->rchild = NULL; } }else{ root = NULL; } delete r; }else if(r->rchild && r->lchild){ //如果左右子树都有(还有一种处理办法就是用右子树的最左结点替换待删除结点,然后删除最左结点) p = r; //寻找右子树的最左结点 r = r->rchild; while(r->lchild){ r = r->lchild; } //将删除结点的左结点接到找到的最左结点之后 r->lchild = p->lchild; r->lchild->parent = r; //删除结点(如果pre是空,说明删除结点是根结点,不用改变前序结点指针) if(pre){ if(pre->lchild == p){ pre->lchild = p->rchild; }else{ pre->rchild = p->rchild; } p->rchild->parent = pre; }else{ p->rchild->parent = NULL; root = p->rchild; } delete p; }else if(r->lchild){ //如果只有左子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->lchild; else pre->rchild = r->lchild; r->lchild->parent = pre; }else{ r->lchild->parent = NULL; root = r->lchild; } delete p; }else{ //如果只有右子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->rchild; else pre->rchild = r->rchild; r->rchild->parent = pre; }else{ r->rchild->parent = NULL; root = r->rchild; } delete p; } } template<class T> void ISet<T>::preSet(Node<T>* t){ if(!t) return; Node<T>* p; //如果t有左孩子,则pre就是左孩子的最右结点 p = t->lchild; if(p){ while(p->rchild){ p = p->rchild; } t->pre = p; }else{//p是空 p = t; if(!t->parent){ t->pre = NULL; }else if(t->parent->lchild == t){//若p为左孩子,则回朔,直到遇到结点是右孩子 while(p->parent){ if(p->parent->rchild == p) break; p = p->parent; } t->pre = p->parent; }else{ //若p为右孩子,则pre是其父 t->pre = t->parent; } } } template<class T> void ISet<T>::nextSet(Node<T>* t){ if(!t) return; Node<T>* p; //如果t有右孩子,则next就是有孩子的最左结点 p = t->rchild; if(p){ while(p->lchild){ p = p->lchild; } t->next = p; }else{ p = t; if(!t->parent){ t->next = NULL; }else if(t->parent->rchild == t){ while(p->parent){ if(p->parent->lchild == p) break; p = p->parent; } t->next = p->parent; }else{ t->next = p->parent; } } } template<class T> typename ISet<T>::iterator ISet<T>::Iterator(){ if(!root) return NULL; Node<T>* p = root; while(p->lchild){ p = p->lchild; } head = p; p = root; while(p->rchild){ p = p->rchild; } tail = p; return head; } template<class T> typename ISet<T>::const_iterator ISet<T>::Iterator() const{ if(!root) return NULL; Node<T>* p = root; while(p->lchild){ p = p->lchild; } head = p; p = root; while(p->rchild){ p = p->rchild; } tail = p; return head; } template<class T> typename ISet<T>::iterator ISet<T>::next(){ Node<T>* t; if(head){ t = head; head = head->next; return t; } return NULL; } template<class T> typename ISet<T>::const_iterator ISet<T>::next() const{ Node<T>* t; if(head){ t = head; head = head->next; return t; } return NULL; } template<class T> typename ISet<T>::iterator ISet<T>::pre(){ Node<T>* t; if(tail){ t = tail; tail = tail->pre; return t; } return NULL; } template<class T> typename ISet<T>::const_iterator ISet<T>::pre() const{ Node<T>* t; if(tail){ t = tail; tail = tail->pre; return t; } return NULL; } template<class T> bool ISet<T>::hasNext(){ if(head) return true; return false; } template<class T> bool ISet<T>::hasPre(){ if(tail) return true; return false; }
main.cpp
#include <iostream> #include "iset.cpp" using namespace std; int main(){ int a[] = {19, 38,1,41,39,54,6,3}; ISet<int> s(a, 8); s.print(); cout<<endl; /* int n = s.size(); cout<<"size:"<<n<<endl; cout<<"isEmpty:"<<s.isEmpty()<<endl; cout<<"contains 4:"<<s.contains(4)<<endl; cout<<"contains 90:"<<s.contains(90)<<endl; int *k = new int[n]; k = s.toArray(); for(int i=0; i<n; i++){ cout<<k[i]<<" ";} cout<<endl; delete k; cout<<"添加5\n"; s.add(5); cout<<"size:"<<s.size()<<endl; s.print(); cout<<"\n添加10\n"; s.add(10); cout<<"size:"<<s.size()<<endl; s.print(); cout<<"\n删除10\n"; s.remove(10); s.print(); cout<<"\n添加三个集合(一个重合)"; int m[] = {4,12,6}; s.addAll(m, 3); cout<<"\nsize:"<<s.size()<<endl; s.print(); s.removeAll(); cout<<"\nsize:"<<s.size()<<endl; s.print(); */ ISet<int>::iterator ite = s.Iterator(); while(s.hasNext()){ cout<<s.next()->data<<" "; } s.remove(41); cout<<endl; ite = s.Iterator(); while(s.hasNext()){ cout<<s.next()->data<<" "; } s.add(10); cout<<endl; while(s.hasPre()){ cout<<s.pre()->data<<" "; } cout<<endl; return 0; }
2.Map的简单实现
map也是利用二叉树实现
imap.h
//二叉排序树 #ifndef IMAP_H #define IMAP_H //数据域,里面存放结点数据 template<class K, class V> struct Data{ K key; //结点数据 V value; }; template<class K, class V> struct Node{ Data<K, V> data; Node<K, V> *rchild, *lchild; Node(){ rchild = lchild = 0; } }; template<class K, class V> class IMap{ public: IMap(); ~IMap(); int size(); bool isEmpty(); bool containsKey(K key); bool containsValue(V value); V get(K key); void put(K key, V value); //若插入的值已经存在,则更新value V remove(K key); void clear(); void print(); private: Node<K, V>* root; Node<K, V>* pre;//用于递归插入时,记录前序结点 void print(Node<K, V>* root); void clear(Node<K, V>* &root); int size(Node<K, V>* root); void containsValue(Node<K, V>* root, V value, bool *b); void deleteNode(Node<K, V>* &root, Node<K, V>* r, Node<K, V>* pre);//删除结点p }; #endif
imap.cpp
#include <iostream> #include "imap.h" using namespace std; template<class K, class V> IMap<K, V>::IMap(){ pre = NULL; root = NULL; } template<class K, class V> IMap<K, V>::~IMap(){ clear(); } template<class K, class V> int IMap<K, V>::size(){ return size(root); } template<class K, class V> bool IMap<K, V>::isEmpty(){ if(!root) return true; return false; } template<class K, class V> bool IMap<K, V>::containsKey(K key){ Node<K, V>* r = root; while(r){ if(r->data.key == key) break; r = (r->data.key > key)?r->lchild:r->rchild; } //如果没找到,返回false if(!r) return false; return true; } template<class K, class V> bool IMap<K, V>::containsValue(V value){ bool b = false; containsValue(root, value, &b); return b; } template<class K, class V> V IMap<K, V>::get(K key){ Node<K, V>* r = root; while(r){ if(r->data.key == key) break; r = (r->data.key > key)?r->lchild:r->rchild; } if(!r) return 0; return r->data.value; } template<class K, class V> void IMap<K, V>::put(K key, V value){ cout<<"插入<"<<key<<", "<<value<<">\n"; Node<K, V>* r = root; if(r == NULL){ Node<K, V>* t = new Node<K, V>; t->data.key = key; t->data.value = value; t->lchild = t->rchild = NULL; root = t;//必须设置新的root结点,因为t和root在内存指向位置不同 }else{ Node<K, V>* p = r; //查找待插入结点位置 while(r){ //如果已经存在,则更新value if(r->data.key == key){ r->data.value = value; return; } p = r; r = (r->data.key > key)?r->lchild:r->rchild; } Node<K, V>* t = new Node<K, V>; t->data.key = key; t->data.value = value; t->lchild = t->rchild = NULL; if((p->data).key > key){//插入左 p->lchild = t; }else{ p->rchild = t; } } } template<class K, class V> V IMap<K, V>::remove(K key){ if(!root) return 0; Node<K, V>* pre = NULL, *r = root; //查找待删除结点位置(pre是r的前序结点) while(r){ if(r->data.key == key){ break; } pre = r; r = (r->data.key > key)?r->lchild:r->rchild; } //没找到 if(!r) return 0; //如果pre == NULL说明是root结点 deleteNode(root, r, pre); return r->data.value; } template<class K, class V> void IMap<K, V>::clear(){ clear(root); root = NULL; } template<class K, class V> void IMap<K, V>::print(){ print(root); } template<class K, class V> void IMap<K, V>::print(Node<K, V>* root){ if(root){ cout<<root->data.value<<" "; print(root->lchild); print(root->rchild); } } template<class K, class V> void IMap<K, V>::clear(Node<K, V>* &root){ if(root){ clear(root->lchild); clear(root->rchild); delete root; } } template<class K, class V> int IMap<K, V>::size(Node<K, V>* root){ if(!root) return 0; else{ return size(root->lchild)+size(root->rchild)+1; } } template<class K, class V> void IMap<K, V>::containsValue(Node<K, V>* root, V value, bool *b){ if(root){ if(root->data.value == value){ *b = true; return; } containsValue(root->lchild, value, b); containsValue(root->rchild, value, b); } } template<class K, class V> void IMap<K, V>::deleteNode(Node<K, V>* &root, Node<K, V>* r, Node<K, V>* pre){ Node<K, V>* p; if(!r->rchild && !r->lchild){ //如果是叶子结点 if(pre){ if(pre->lchild == r){ pre->lchild = NULL; }else{ pre->rchild = NULL; } }else{ root = NULL; } delete r; }else if(r->rchild && r->lchild){ //如果左右子树都有(还有一种处理办法就是用右子树的最左结点替换待删除结点,然后删除最左结点) p = r; //寻找右子树的最左结点 r = r->rchild; while(r->lchild){ r = r->lchild; } //将删除结点的左结点接到找到的最左结点之后 r->lchild = p->lchild; //删除结点(如果pre是空,说明删除结点是根结点,不用改变前序结点指针) if(pre){ if(pre->lchild == p) pre->lchild = p->rchild; else pre->rchild = p->rchild; }else{ root = p->rchild; } delete p; }else if(r->lchild){ //如果只有左子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->lchild; else pre->rchild = r->lchild; }else{ root = r->lchild; } delete p; }else{ //如果只有右子树 p = r; if(pre){ if(pre->lchild == p) pre->lchild = r->rchild; else pre->rchild = r->rchild; }else{ root = r->rchild; } delete p; } }
main.cpp
#include <iostream> #include "imap.cpp" using namespace std; int main(){ IMap<int, int> map; cout<<"当前map:"<<map.isEmpty()<<endl; cout<<"当前map长度:"<<map.size()<<endl; map.print(); int key[] = {0,1,2,3,4,5,6,7,8,9}; int value[] = {21,34,32,34,56,6,78,76,111,13}; for(int i=0; i<10; i++){ map.put(key[i], value[i]); } cout<<"当前map长度:"<<map.size()<<endl; map.print(); cout<<endl; bool b = map.containsKey(5); if(b) cout<<"包含键5:"<<map.get(5)<<endl; else cout<<"不包含键5\n"; b = map.containsKey(12); if(b) cout<<"包含键12:"<<map.get(12)<<endl; else cout<<"不包含键12\n"; b = map.containsValue(111); if(b) cout<<"包含值111:"<<111<<endl; else cout<<"不包含值111\n"; b = map.containsValue(211); if(b) cout<<"包含值211:"<<211<<endl; else cout<<"不包含值211\n"; cout<<"移除6\n"; map.remove(6); cout<<"当前map长度:"<<map.size()<<endl; map.print(); cout<<endl; cout<<"移除90\n"; map.remove(90); map.print(); cout<<endl; return 0; }