C++ <七>

//-----------------不为有希望才坚持,只因坚持才有希望-------day_15_AM-------------------------------------

/*回顾: 栈和队列

栈: 先进后出,前插前取(链表)(数组)

队列:后插前取(链表)(数组)//用数组实现的时候要考虑满还是没满;

二叉树的查找:【 root, left, right】;根节点(创建)Node* root =NULL;

没有根节点的时候不能访问根节点中的数据; 可能会出现段错误;

大量利用递归(整棵树的问题变成某个分支的问题,考虑怎样结束)

【树的高度】: 比较左右子树的高度,取其较高的再加上1 空树的高度为0;

删除某个节点:找到  左根插入右子树 指针指向右子树;

选择排序:两层循环; 【递归实现的一般都可以用循环和栈来实现】

*/

/*冒泡排序:每次只能比较相邻的两个元素,如果顺序不合适就交换;

排好序的标志是一轮比较下来没有发生交换;【多轮排序】,只要发生过交换则需要再进行至少一轮比较;

*/

/*

#include<iostream>//【冒泡排序】适用于一组数据不是很混乱的情况下使用;

using namespace std;//只能交换相邻的两元素

typedef int T;

#include<ctime>

void sort(T *a,int n)

{

       bool bSwap=false;

       do{

              bSwap=false;

              for(int i=1;i<n;i++)

              {

                     if(a[i]<a[i-1])

                     {

                            swap(a[i],a[i-1]);

                            bSwap=true;

                     }

              }

              n--;//每次交换后最后一个元素总是最大的不需要再参与排序

       }while(bSwap);//大括号内定义的变量只能在大括号内部使用;

}

int main()

{

       const long N=30240;

       int a[N];

       for(int i=0;i<N;i++)

              a[i]=N-i;

       time_t t1=time(NULL);

       sort(a,N);

       time_t t2=time(NULL);

       for(int j=0;j<20;j++)

              cout<<a[j]<<' ';

              cout<<endl;

              cout<<"time="<<t2-t1<<endl;

}*/

/*【插入排序:】

除了第一个元素对每个新元素:

1)找左边合适的插入位置;先复制一份保存;

2)把从那个位置开始的所有数据右移一个位置;

3)边元素放到插入位置;

 

#include<iostream>//【大量数据移动】导致其排序速度变慢;

using namespace std;

#include<ctime>

typedef int T;

void sort(T*a,int n)

{

       T temp=0;

       for(int i=1;i<n;i++)

       {

              int pos;

              temp=a[i];

              for(pos=i;pos>0/*&&a[pos-1]>temp;pos--)

                     if(a[pos-1]>temp)

                     a[pos]=a[pos-1];

               a[pos]=temp;

       }

}

 

int main()

{

      

       const long N=30240;

       int a[N];

       for(int i=0;i<N;i++)

              a[i]=N-i;

       time_t t1=time(NULL);

       sort(a,N);

       time_t t2=time(NULL);

       for(int j=0;j<20;j++)

              cout<<a[j]<<' ';

              cout<<endl;

              cout<<"time="<<t2-t1<<endl;

}

*/

 

/*快速排序:(最快的排序方法) 选出一个分界值把数组分为两个部分,

递归调用知道各部分中不超过一个元素结束;

取第一个、中间那个、 最后一个、 取三者中中间大小的值最为分界

 

#include<iostream>

using namespace std;

#include<ctime>

typedef int T;

void sort(T* a,int n)

{

       if(n<=1) return;//必须有递归结束条件;

       swap(*a,a[n>>1]);

       T *L=a+1;//从左边找比分界大的;

       T* R=a+n-1;//从右边找比分界小的;

       T V=*a;//分界

       while(L<R){//1248945323456546

              while(*L<V&&L<R) L++;

              while(*R>=V&&R>a) R--;

              if(L<R)

                     swap(*L,*R);

       }

       if(V>*R) swap(*a,*R);

       sort(a,R-a);//左边组递归

       sort(R+1,n-1-(R-a));//右边组递归

}

 

 

int main()

{

       const long N=102400;

       int a[N];

       for(int i=0;i<N;i++)

              a[i]=N-i;

       time_t t1=time(NULL);

       sort(a,N);

       time_t t2=time(NULL);

       for(int j=0;j<20;j++)

              cout<<a[j]<<' ';

              cout<<endl;

              cout<<"time="<<t2-t1<<endl;

}

 

//四种排序算法

#include<iostream>

using namespace std;

#include<ctime>

typedef int T;

void Ssort(T* a,int n)

{

       for(int i=0;i<n-1;i++)

       {

        int t=i;

              for(int j=i+1;j<n;j++)

                     if(a[j]<a[t])

                     {

                            t=j;

                     }

                     swap(a[i],a[t]);

       }

}

 

void Msort(T* a,int n)

{

              bool bSwap=false;

       do{

               bSwap=false;

              for(int i=0;i<n-1;i++)

              {

              if(a[i]>a[i+1])

              {

                     swap(a[i],a[i+1]);

                  bSwap=true;

              }

              }

       }while(bSwap);

 

}

void Isort(T* a,int n)

{

       for(int i=1;i<n;i++)

       {

              T temp=a[i];

              int pos;

              for(pos=i;pos>0;pos--)

                     if(a[pos-1]>temp)

                            a[pos]=a[pos-1];

                     a[pos]=temp;

       }

       n--;

}

void Qsort(T *a,int n)

{

       if(n<=1) return;

       swap(a[0],a[n>>1]);

       T *L=a+1;

       T* R=a+n-1;

       while(L<R)

       {

              while(*L<*a&&L<R) L++;

              while(*R>=*a&&R>a) R--;

              if(L<R)   swap(*L,*R);

              if(*R<*a) swap(*R,*a);

       }

       Qsort(a,R-a);

       Qsort(R+1,n-1-(R-a));

}

       int main()

{

       const long N=10240;

       int a[N];

       for(int i=0;i<N;i++)

              a[i]=N-i;

       time_t t1=time(NULL);

       Ssort(a,N);

       //Msort(a,N);

       //Isort(a,N);

       //Qsort(a,N);

       time_t t2=time(NULL);

       for(int j=0;j<20;j++)

              cout<<a[j]<<' ';

              cout<<endl;

              cout<<"time="<<t2-t1<<endl;

}

             

*/

 

/*【模板】:自定义、 标准模板库(STL);【C++标准程序库--华中科技大学出版社】

*/

/*

#include<iostream>

using namespace std;

template<typename T>//函数模板, 每次定义都要有属于自己的template<typename T>

//typedef int T;//给定模板让编译器去猜属于哪种类型的

void sort(T *a ,int n)

{

       for(int i=0 ;i<n;i++)

              for(int j=0;j<i;j++)

                     if(a[i]>a[j])

                            swap(a[i],a[j]);

}

template<typename T>

void disp(T * a,int n)

{

       for(int i=0;i<n;i++)

              cout<<a[i]<<' ';

       cout<<endl;

}

 

int main()

{

       double ad[5]={3.3,5.5,2.2,1.1,0.0};

       int cd[5]={3,5,6,7,3};

       char ac[4]={'x','s','a','d'};

       sort(ad,5);

       sort(cd,5);

       sort<char>(ac,4);//不指定为char类型的话,编译器会自行去猜

       disp(ad,5);

       disp(cd,5);

       disp(ac,4);     

}

*/

//【函数模板】

//模板编程又称通用类型编程;

//泛型编程;

/*

#include<iostream>

using namespace std;

#include<string>

template<typename T>

//typedef int T;//给定模板让编译器去猜属于哪种类型的

void sort(T *a ,int n)

{

       for(int i=0 ;i<n;i++)

              for(int j=0;j<i;j++)

                     if(a[i]>a[j])

                            swap(a[i],a[j]);

}

template<typename T>

void disp(T * a,int n)

{

       for(int i=0;i<n;i++)

              cout<<a[i]<<' ';

       cout<<endl;

}

void sort(char *  a[],int n)//特殊的,

{

       for(int i=0;i<n;i++)

          for(int j=i+1;j<n;j++)

              if(strcmp(a[j],a[i])<0)

                     swap(a[i],a[j]);

}

int main()

{

       double ad[5]={3.3,5.5,2.2,1.1,0.0};

       int cd[5]={3,5,6,7,3};

       char*ac[4]={"xy","st","ab","cd"};//string ac[4]={"xy","st","ab","cd"};

//特殊的,可以特殊定义、实现模板的重载;

//【编译器会优先选择非模板函数;定义模板的时候声明和定义不要分开;】

       sort(ad,5);

       sort(cd,5);

       sort(ac,4);

       disp(ad,5);

       disp(cd,5);

       disp(ac,4);     

}

*/

//取得数组中最大元素的下标;

/*

#include<iostream>

using namespace std;

 

template<typename T>//templata<class T>

int max(T *a,int n)//模板要将整个定义都放在头文件中;

{

       int MAX=0;

       for(int i=1;i<n;i++)

       {

              if(a[MAX]<a[i])

              MAX=i;

       }

       return MAX;

}

 

int main()

{

    int a[5]={3,4,7,1,2};

       char b[5]={'a','d','t','z','f'};

       cout<<max(a,5)<<endl;

       cout<<max(b,5)<<endl;

}*/

//【类模板】 与函数模板类似; 在使用类模板时必须明确指定模板形参类型

// 把模板形参确定为具体类型的过程称为【模板的实例化】; Stack<int> si; Stack<doble> sd;

//模板名<类型实参>共同构成类名; void show(Stack<T>) 增加必要的限制;

//【 多个不确定类型模板】

/*

#include<iostream>

using namespace std;

#include<string>

template<typename T,typename U>

struct Pair{

       T first;

       U second;

       Pair():first(T()),second(U()){}//初始化避免垃圾数据

       Pair(const T& f,const U& s):first(f),second(s){}

};   

template<typename T,typename U>

void show(const Pair<T,U>& p)

{

       cout<<p.first<<','<<p.second<<endl;

}

 

template<typename T,typename U>

Pair<T,U> mkpair(T f,U s)

{

       return Pair<T,U>(f,s);

}

 

int main()

{

    Pair<int,double> p1;

       Pair<int ,string> p2(100,"hello");

    show(p1);

       show(p2);

       show(mkpair('c',5));

    show(Pair<char,int>('c',5));//<char,int>显得有点多余,后面的实参已经指定了类型;

 

}*/

//STL C++标准模板库--类模板;

//容器(container) 类模板---一般都有一个内部类iterator(迭代器)【指针】

//函数模板(通用算法);

//class iterator{ //智能指针,类模板中一般不直接使用指针而是用迭代器代替

//   T *p;

//public://模仿指针的运算。【perator* 、operator ->/ operator++ --、operator == !=】

 //      iterator();

  //     iterator(const iterator& i");

  //     iterator(T* q);

//};

//区间为半开半闭  [begain,end) end 所指元素不在区间中;

//【容器】: 序列式容器(vector【动态数组】,deque [双端队列],List[双向链表]),

//关联式容器(都是二叉查找树模板)(map不可重复【映射】、multimap可重复【多映射】、set【数据集】、multiset【多数据集】)

/*容器的共性:

区间是由两个迭代器决定的一个范围;

vector<int> v1;//构造函数

vector<int>v2(v1);//拷贝构造函数

vector<int> v3(begain,end)//区间构造函数

容器支持运算符:=,>,>=,<,<=,==,1=;

intsert(迭代器,要插入的元素)//复制一份;

erase();

size()//已有元素的大小

empty()//容器是否为空

max_size()//这中容器的最大容量

clear()//清除容器

swap(c2)//交换两个容器

 使用时都需要包含相应的头文件, 头文件名和容器名一致

 begin()/end()都是成员函数、 begin() 指向第一个元素、end()指向最后一元素之后

end()所指向的元素不属于这个容器;

 

#include<iostream>

using namespace std;

#include<list>

 

int main()

{

       list<int> l1;

       int a[5]={3,4,5,6,7};

       list<int> l2(a,a+5);

       cout<<"l1.size():"<<l1.size()<<endl;

       cout<<"l2.size():"<<l2.size()<<endl;

       list<int>::iterator it;

       for(it=l2.begin();it!=l2.end();it++)

              cout<<*it<<' ';

       cout<<endl;

       it=l2.begin();

       it++;

       l2.erase(it);

       l2.insert(l2.begin(),100);

       l2.insert(l2.end(),200);

       for(it=l2.begin();it!=l2.end();it++)

              cout<<*it<<' ';

       cout<<endl;

}

*/

//作业:递归选择排序, 找最大的元素与最后一元素交换递归 注意递归条件

/*

#include<iostream>

using namespace std;

 

template<typename T>

void Dssort(T* a,int n)

{

       if(n<=1) return;

       int max=0;

       for(int i=1;i<n;i++)

              if(a[max]<a[i])

                     max=i;

              swap(a[max],a[n-1]);

              n--;

              Dssort(a,n);

}

template<typename Q>

void disp(Q *a,int n)

{

       for(int i=0;i<n;i++)

              cout<<a[i]<<' ';

       cout<<endl;

 

}

 

int main()

{

       int a[10]={1,3,4,6,2,5,7,8,0,11};

       char b[10]={'l','k','j','h','g','f','d','s','a','t'};

       Dssort(a,10);

       Dssort(b,10);

    disp(a,10);

       disp(b,10);

}

*/

//--------------踏实------day_16_AM-------------------------------

/*回顾:

 排序算法:注意逻辑的严密性;不要出现野指针, 【Node* p=NULL;】

 选择排序、冒泡排序、插入排序、快速排序;

 模板: 声明和定义不要分开; 自定义模板( tempplate<typename T>   类模板<类型> 标准模板库STL;

 容器: 都支持构造【 构造函数、拷贝构造函数、区间构造函数】

 指定位置插入、删除、比较、 size()、empty()、clear()

【 反向迭代器 reverse_iterator】: rbegin()/rend()

【const_iterator】

【const_reverse_interator】

容器适配器:stack、queue、priority_queue(优先队列、操作和栈一样,头文件使用的是队列一样)

容器: 序列式容器【sequence】--vector、list、deque,

共性:

构造函数 constructor(int n),constructor(int n,T val)  、

调整大小 resize(int n)/ resize(int n,T val);

赋值 assign(n,val): 清除原来的数据、在容器中放n个val的数据  assign(区间)

插入 insert(pos,n,val)/insert(pos,区间)【pos为iterator】/

末未插入新数据:push_back(val)

首尾元素:   front()/back()

尾删除:pop_back();

//有了序列容器可以不再使用动态内存

序列容器的特性:

vector 类似于动态数组但更加安全,能自动增长;

可以检查下表是否越界 at(下标),只适合在末尾插入删除数据,

在头部会有大量的数据移动

reserve(int n) 保留容量

capacity() 取得当前的容量;

deque  是vector的子类,可以从头尾操作;deque相比vector多了 push_front(val) pop_front();

list  可以在任何位置插入删除, 查找的效率较低;

支持 push_front  push_back()  pop_back() pop_front();

不支持[]/at  因为它的数据在内存中不是连续存放的;

【sort()需重载<】; 【unique() 需重载 ==】

splice 转移  c1.splice(c2) :c2中的数据转移到c1  转以后c2中不在有元素

c1.splice(pos,c2)

c1.splice(pos,c2,it);把c2中it位置的数据转移到c1中的pos位置,其中pos,it都为迭代器

c1.splice(pos,c2,区间) 把c2中该区间中的数据转移到c1的pos位置

c1.merge(c2) 把c2中的元素归并到c1的合适位置【归并排序】 归并后c2为空链表

c1.remove(val)//删除指定元素

*/

/*

#include<iostream>

using namespace std;

#include<vector>//可以替代new操作,免了delete操作

void show(vector<int> vi)

{

       vector<int>::iterator it;

       for(it=vi.begin();it!=vi.end();it++)

       {

              cout<<*it<<' ';

       }

       cout<<endl;

}

 

 

int main()

{

       vector<int> vi(3,90);

       show(vi);

       int a[5]={3,4,5,6,7};

       vi.insert(vi.begin(),a,a+5);

       show(vi);

       vi.push_back(100);

       show(vi);

       cout<<"size:"<<vi.size()<<endl;

       vi.assign(5,99);

       show(vi);

       cout<<"size:"<<vi.size()<<endl;

}

 

#include<iostream>

using namespace std;

#include<vector>

 

int main()

{

       vector<int> vi;

       cout<<"input scores, end by -1:";

       int s;

       int m=0;

       for(;;){

              cin>>s;

              if(s==-1) break;

              vi.push_back(s);

              if(s>m)

                     m=s;

}

       int inc=100-m;

       for(int i=0;i<vi.size();i++)

       {

              vi[i]+=inc;

       }

       for(int j=0;j<vi.size();j++)

       {

              cout<<vi[j]<<' ';

       }

       cout<<endl;

       try{

       cout<<"vi[1000]="<<vi[1000]<<endl;//尽量使用[],避免使用at(),自行设置下标

              cout<<"vi.at(1000)="<<vi.at(1000)<<endl;//at检测下标是否越界,会减低性能

       }catch(exception &e){//标准库中的异常都可以用他来catch;

              cout<<e.what()<<endl;

       }

}

*/

/*

#include<iostream>

using namespace std;

#include<list>

int main()

{

       int cpp[5]={3,6,1,7,5};

       int java [8]={6,4,7,8,15,2,3,9};

       int unix[4]={5,2,6,9};

       list<int> li;

       li.insert(li.begin(),cpp,cpp+5);

       li.insert(li.begin(),java,java+5);

       li.insert(li.begin(),unix,unix+5);

       li.sort();

       li.unique();//相邻两元素不相同;

       list<int>::iterator it=li.begin();

       while(it!=li.end())

       {

              cout<<*it++<<' ';

       }

       cout<<endl;

 

}

*/

/*【关联式容器】:数据之间存在关系;

共性:

insert(val);不需要指定位置, 只要给数据就可以;会自动找到合适的位置,排好序;

find(val);查找一个指定的数据;返回指向找到元素的迭代器;没找到返回end() ,并非NULL

multimap/multiset://允许有重复元素

  count(val);统计指定值的个数:

  lower_bound(val)  指定值的第一个位置

  upper_bound(val) 指定值最后一个后面一个位置

  [lower_bound(val),upper_lound),,为指定值的区间;

  equal_range(val);//返回迭代器; Pair(迭代器1,迭代器2),迭代器1==lower_lound(val);迭代器2==upper_lound(val);

  特性:

  map:      可重复,  Pair<key,value>; key->value (key唯一,可做索引找到value,支持"[key]"方括号操作)

  multimap: 不重复, Pair<key,value>

  set:      可重复, key

  multiset: 不重复, key

//不可重复指的是key不允许重复;

 

#include<iostream>

using namespace std;

#include<map>

#include<string>

 

int main()

{

       map<int,string> mis;

       mis.insert(make_pair(63,"李鹏"));

//     mis.insert(make_pair(32,"王媛"));

       //mis.insert(make_pair(36,"李鹏"));

       mis[20]="覃丹";

       //mis.insert(make_pair(32,"娜娜"));//重复时不再插入;

//     map<int,string>::iterator it;

//     it=mis.begin();

//     while(it!=mis.end()){

//            cout<<(it->first)<<":"<<(it->second)<<endl;

//            ++it;

//     }

 

}

 

#include<iostream>

using namespace std;

#include<map>

#include<string>

 

int main()

{

       typedef multimap<string,string> Mul;

       Mul mss;

       Mul::iterator ib,ie;

       mss.insert(make_pair("aa","aa"));

       mss.insert(make_pair("cc","dd"));

       mss.insert(make_pair("ee","ff"));

       mss.insert(make_pair("cc","pp"));

       mss.insert(make_pair("aa","mm"));

       mss.insert(make_pair("cc","dd"));

       mss.insert(make_pair("aa","kk"));

       ib==mss.begin();

       ie=mss.end();

       while(ib!=ie){

              cout<<ib->first<<"的好友"<<ib->second<<endl;

           ++ib;

       }

       cout<<"aa的好有个数:"<<mss.count("aa")<<endl;

    ib=mss.lower_bound("cc");

    ie=mss.upper_bound("cc");

    cout<<"cc的好友:"<<endl;

    while(ib!=ie){

       cout<<ib->second<<endl

}//都是按key来排序的,与value无关系,  所以必须支持<操作符;

}

*/

/*

set:

multiset:

 

#include<iostream>

using namespace std;

#include<set>//用set 设置用户权限

 

int main()

{

 

       //set<int> si;

       int userid[5]={3,8,6,4,3};//重复的插入被忽略

       //for(int i=0;i<5;i++)

//     si.insert(userid[i]);

       set<int> si(userid,userid+5);

       set<int>::iterator it;

       it=si.begin();

       while(it!=si.end())

              cout<<*it++<<' ';

              cout<<endl;

              cout<<"user 3:"<<(si.find(3)!=si.end())<<endl;

              cout<<"user 5:"<<(si.find(5)!=si.end())<<endl;

 

}

算法: for_each()对每个元素调用指定的函数,for_each(beg,end,函数名)

//find(begin,end,数据)算法一般都工作在区间内;

头文件<algorithm>

find_first_of(),find_end()

sort(),reverse()

copy() copy_backward()

replace(),merge(),

remove();//假删除, 需使用容器的erase才能真正删除;

头文件<numeric>

min(),cout(),swap(),accumulate()

*/

 

/*

复习:

 基本语法: 流程控制, 函数(static可延长生命期),

 递归(每次执行完都回到调用它的位置,一定要有结束条件,否则会出现段错误),

 引用:初始化引用时要用长久不改变的变量; const T& ,直接使用旧变量

 指针:指针不是最重要的;指针只能保存地址,地址也只能用指针来保存; 指针与*指针区别;

 函数名就是函数的地址, 向定义函数一样第一函数指针指示将函数名改成(*指针)  new 类型 [个数]     delete []  p;

 动态内存的使用;可以利用vector来代替动态数组;

 oo面向对象编程:

  定义类:创建对象是自动调用相对应的构造函数, 拷贝构造函数,

  默认拷贝构造函数(按字节复制) 如果存在继承关系, 默认调用父类的无参构造函数,

  使用对象: 对象.成员函数; 继承: 子类继承父类子类的全部成员, 也可自行定义覆盖父类的

  多态: 统一管理,以父类身份统一管理子类;虚函数,  通过指针或者引用

  扩展:

  运算符的重载: ,友元形式;  operator ¥ (-,-)

  成员形式 : 默认使用当前对象, 只需传递剩余参数;

  前++,-- 后++,--;  多传递一个int形参;

   <<  >>  istream & operator >>(istream& s,T & o)

            ostream & operator <<(ostream& s,T & o)

  类型转换: operator int()  不需要写返回类型,

  静态: 共用一份, 属于整一个类,想定义全局变量一样定义;

  IO:   文件对象的创建; istream fout("文件名"), 文件操作与控制台的操作一样;

  异常: try { }catch{}

  模板:  template<typename T>; 函数模板编译器主动识别, 类模板需要主动实例化

  类模板->容器, 函数模板-> 算法 , 通过迭代器iterator将容器和算法联系起来;

  数据结构: 链表【注意段错误】, 栈【前插前去LIFO】,队列【FIFO】, 二叉树

  算法: 选择排序,冒泡排序,插入排序,快速排序

  无参的函数一般不能递归;

 

 

posted @ 2013-03-08 14:09  ReaLo  阅读(252)  评论(0编辑  收藏  举报