set和map的简单实现

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值