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;
}
#include "MyTracer.h"XxwTracer::XxwTracer(QCustomPlot*_plot, TracerType _type, QObject *parent): QObject(parent),m_plot(_plot),m_type(_type){m_visible= true;m_tracer= Q_NULLPTR;//跟踪的点m_label = Q_NULLP...
前提:spring对于java程序员来说,无疑就是吃饭到筷子。在每次编程工作到时候,我们几乎都离不开它,相信无论过去,还是现在或是未来到一段时间,它仍会扮演着重要到角色。自己对spring有一定的自我见解,所以参考网上的视频和文章,整理出一套简单的SpirngMVC。内容较多,项目地址先贴出来,接下来大概讲下流程。手写简单的SpringMvc框架。主要分为几个步骤:扫描包下面的文件。根据扫描到到文件,初始化bean工厂。根据@Controller @RequestMapping 注解,处理映
点击上方“AI算法修炼营”,选择加星标或“置顶”标题以下,全是干货论文地址:https://arxiv.org/abs/2003.05128代码地址:https://github.co...
map()实现类型转换接收一个函数作为方法参数,这个函数会被应用到集合中每一个元素上,并最终将其映射为一个新的元素案例:将List 转换Listpublic class MapDemo { static class KeyValue { private Integer key; private String value; public KeyValue(Integer key, String value) { thi
使用MATLAB多项式曲线拟合实现&lt;script&gt;&lt;/script&gt;%多项式曲线拟合x=[-3.6 -1.8 0 3.3 4 5 6 6.4 7 7.4 8 8.6 9 10 15 26 27 28 29 30 31 32 33 34 35 36 37 38 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 5...
static void RCC_Configuration(void);static void GPIO_Configuration(void);static void ADC_Configuration(void);static void DMA_Configuration(void); void SetupADC(void) { RCC_Configur
<br /> 今天由于工作需要,暂时搁置一下,今晚先不学习鸟哥了, 因为今天还有任务需要完成。但根据自己遇到的问题,进行一篇好文章的转帖。以后需要的时候可以用。<br /> <br />从 http://www.congci.com/item/cjichengduotai 中转<br /> <br /> 1、引言<br />继承和多态是面向对象语言最强大的功能。有了继承和多态,我们可以完成代码重用。在C中有许多技巧可以实现多态。本文的目的就是演示一种简单和容易的技术,在C中应用继承和多态。通过创建一个V
在servlet同步请求中,当一个http请求过来的时候,务器端tomcat的线程池都要分配一个线程去处理这个请求,如果这个请求耗时很长,则这个线程会一直占用,则tomcat线程池容易爆满在servlet3.0新特性AsyncContext出现之后,及tomcat7之后,当服务端,开启AsyncContext处理的时候,就可以释放这个线程,供其他客户端使用,这样可以大大提高整个系统的并发性,但是服务端需要保存客户端状态信息,占用一定的内存资源,下面举一个实例:@[email protected]
QT编译Mysql驱动文件
将一个类的接口转换成客户期望的另一个接口
http://www.linuxidc.com/Linux/2011-05/35982p5.htm移植环境1,主机环境:VMare下CentOS 5.5 ,1G内存。2,集成开发环境:Elipse IDE3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。4,开发板:mini2440,2M nor
ADC的认识1 ADC初始化参数/* Exported types ------------------------------------------------------------*//** * @brief ADC Init structure definition */typedef struct{ uint32_t ADC_Resoluti...