数据结构 算法与应用(c++ 描述) 自练答案

目录

                                 第一章

                             第二章(时间/空间复杂度)

                                       第三章          

                                  第四章

                                        第五章 

                                          第六章 

                                              第七章

                                     第八章

                                    第九章

                                       第十章

                                       第十一章

                                        第十二章


有不正确请提出

                                 第一章

1.1

  应该把形参 换成引用  

          int x--> int &x 

1.2

#include<iostream>
using namespace std;
template <class T,class T1>  //模板形参的类型 
int 
count (T array,int end,T1 value){   
    int i =0,count=0;
      while(i<end){
            if (array[i++] ==  value)
                  count++;
      }
        return count ;

}

int main(){
    int array[]{23,45,6,0,0,77,99,7};
   cout<< count(array,sizeof(array)/sizeof(array[0]),0);
}

1.3

#include<iostream>
using namespace std;
template <class T,class T1> 
int
fill(T array,int end,T1 value){
     int i =0;
      while(i<end){
          array[i++]= value;
      }
      return 1;
}


int main(){
    int array[10];
   cout<< fill(array,10,66);
     cout << array[8];
}

1.4

#include<iostream>
using namespace std;
template<class T,class T2>
int 
inner_product(T a1, T a2,T2 n){
    int i=0;
      int value=0;
        while( i<n){
             value = value +a1[i]*a2[i];
             i++;
        }
          return value;
}

int main(){
    int a[]={1,2,3,4};
    int b[]={10,10,100};
      cout<< inner_product(a,b,3)<<endl;
}

1.5

#include<iostream>
using namespace std;
template<class T>
void 
iota (T array,int n){
      int i=0;
       while( i!=n){
            array[i] += i;
             i++;
       }
}
int main(){
    int a[]{1,2,3,4,5,6};
     iota(a,5);
      for(int i=0;i!=5; i++){
           cout<<a[i];
      }
       return 0;
}

1.6

   应该还包括递减的情况

#include<iostream>
using namespace std;
template<class T>
bool 
is_sorted(T array,int n){
      int i=0;
       while(i!=n-1){
           if(array[i]>array[i+1])
               return false;
                i++;
           
       }
         return true;
}

int main(){
    int a[]{1,4,6,78,666};
      cout<< is_sorted(a,5);
        return 1;
}

1.7

#include<iostream>
using namespace std;
template<class T>
int
mismatch(T a,T b,int end){
     int i(0);
       while( i!=end){
            if(a[i]!= b[i])
              return i;
               i++;
       }
         return -1;
}
int main(){
    int a[]{1,2,34,6};
    int b[]{1,2,6,888};
      cout<< mismatch(a,b,4);
       return 0;
}

1.8

  具有相同的签名 ,形参的个数和类型相同,与返回值无关

1.9

都调用模板abc, 因为有三个形参

1.10  /1.11

#include<iostream>
using namespace std;
int 
abc(int a,int b,int c){
     if(c<1)
        throw "有异常!!!";  // 抛出异常

       return a+b+c;
}
int main(){
     try{
          cout<<abc(-2,-3,-5)<<endl;
           
     }
      catch (int value){ //补货整型
          cout<< value;
      }
       catch (const char *c){ //字符串常量是 const char*
            cout <<c<<endl;
       }
        return 0;
          
}

1.12

#include<iostream>
using namespace std;
template <class T,class T1>
bool
make2_array(T **&array,int number_OF_rows,T1 row_Size){
        int i=0;
     try{
          array = new T* [number_OF_rows]; //创建数组指针 类型就是 T **
     
         while(i< number_OF_rows){
              array[i] =  new T [ row_Size[i] ];
              i++;
         }
           return 1;
     } 
       catch (bad_alloc){
              return false;
       }
}
int main(){
     char **a;
     int row_size[]{1,2,4,5,6};
      cout<< make2_array(a,3,row_size);

      return 1;
}

1.13

#include<iostream>
using namespace std;
template<class T>
T*
change_Length(T *a,int newLength,int oldlength){
     if(newLength <=oldlength)
       return NULL;
           T *newArry = new T [newLength];
        
        for(int i=0; i<oldlength;i++){
             newArry[i] = a[i];
        }
          delete [] a;  // 
          
           return newArry;
}
int main(){
     int a[]{1,2,4,5,6};
       int oldlength = sizeof(a)/sizeof (a[0]);
      int * newp =  change_Length(a,10,oldlength);
       cout << "new array size is: "<< sizeof(sizeof(a)/sizeof (a[0]))<<'\n'<< newp[2];

       return 0;
}

1.14

注意: 为数组声明空间时 new 后面的无名数组的 数组名类型必须与 初始化的对象一致

   如

int ** a = new int *[]; 
//int *[] 是个无名数组 ,数组名类型为 int** 与 a一致  可以赋值
#include<iostream>
using namespace std;
template<class T >
T**
changeLength_2D(T ** &array,int row,int col,int oldRow,int oldCol){
    T ** newRow= new T * [row];
     for(int i=0;i <col ;i++){
           newRow[i]= new T[col];
     } //init
      
       for (int i=0;i<oldRow;i++){
            for(int j = 0;j<oldCol;j++){
                 newRow[i][j]= array[i][j]; 
                 delete [] array[i];
            }
       }
         delete [] array;
         return newRow;
}
int main(){
      int **a = new int *[3];
        for( int i=0;i<3;i++){
             a[i] = new int [5];
        }
          for(int i=0;i<3;i++){
              for(int j=0;j<5;j++){
                   a[i][j]=666;
              }
          }
      int ** new_a= changeLength_2D(a,10,10,3,5);
      new_a[9][9]=999;
       cout<< new_a[2][3]<<' '<<new_a[9][9];

       return 0;
}

1.15

    [-max_number / 101 ,+max_number/101]

    (不确定   dollar *100 + cents <= max number) 

1.16

 (转换出现了问题)

#include<iostream>
using namespace std;
enum signType{plus,minus};
class currency{
   
     public:
       currency (signType theSign= signType::plus,unsigned long theDollars=0,unsigned int theCents = 0); //构造函数  外部定义  诺省初始值--> 则按此默认给
        ~currency(){};//析构函数 为空 
        void setValue(signType,unsigned long,unsigned int ); //原型 定义在class 外部 
        currency add(const currency&) const; //此const表示 不改变参数的内容 
        void output() const;
        void input(); //(1)
        double  subtract(double x);//(2)
        currency percent(double x);//3
        currency mulitiply(double x);
        currency div(double x);



        private :  //只能通过成员函数访问  不能对象私自 访问
            signType sign;
            unsigned long dollars;
            unsigned int cents;
}; //最后也要加分号

 currency::currency (signType theSign,unsigned long theDollars,unsigned int theCents){
     setValue(theSign,theDollars,theCents);
}
void currency::setValue(signType Sign,unsigned long Dollars,unsigned Cents){ // 如显示初始化对象 ,则调用此  64row
    //给调用对象 的成员赋值 
     if(Cents >99){
          throw "Max of Cents";
     }
      sign = Sign;   //没用 . 就代表 访问 调用对象的成员 
      dollars = Dollars;
      cents = Cents;
}
currency currency::add(const currency & x) const{
    currency result;
    long a1,a2,a3;
    a1=dollars*100 + cents;  //a1 调用对象的 转换为数字值 
    if(sign ==signType:: minus)
       a1 = -a1;

       a2 = x.dollars*100 +x.cents; // a2 代表形参传进来的对象 
        if(x.sign == signType:: minus)
          a2= -a2;
      
       a3= a1+a2;
        if(a3<0){
             result.sign =signType:: minus;
              a3 = -a3;
        }
           else  result.sign = signType::plus;

        result.dollars = a3/100;
        result.cents = a3-result.dollars*100;

        return result;
          
}
 void currency::output() const{
      if(sign == signType::minus)
        cout<<'-';
          cout<< dollars
               << '.'
                << cents <<'\n';
 }
 void currency::input(){
        double temp;

        cin>> temp;
        temp *=100;    
          if(temp <0){
             sign = signType::minus; 
             temp = -temp;
          }
              else sign =signType:: plus;
                                                                                                                                                                                                                                                                                                                            
        dollars =(unsigned long)temp/100;
         if(temp <0){
               cents = (unsigned) (temp-0.01 -dollars*100);
         }
           else  cents = (unsigned)(temp+0.01 - dollars*100);
          
                     
 }
double currency::subtract(double x){
     double temp = dollars*100+cents ;
     return temp/100 -x;
}
currency currency:: percent(double x){
     currency result;
     double temp = dollars*100+cents ;
     temp =temp* (x/100);
     result.dollars = temp /100;
     result.cents = temp -dollars*100;
      return result;
}
 currency currency:: mulitiply(double x){
      double temp= (dollars*100+cents )/100;
      temp *=x;
      currency result;
      result.dollars = temp;
       if(temp <0){
               result. cents = (unsigned) (temp-0.01 -dollars*100);
         }
           else  result. cents = (unsigned)(temp+0.01 - dollars*100);
          
      return result ;
      
 }
 currency currency:: div(double x){
       double temp= (dollars*100+cents )/100;
       temp /=x;
       currency result;
       result.dollars = temp;
      result.cents = (temp-dollars)*100;
      return result ;
 }
int main(){
    currency a(signType::plus,3,22),b(signType ::minus,2,22);
    a.input();
    a.output();
    a.div(10).output();
    a.mulitiply(5).output();
    //cout<< a.subtract(2.9)<<'\n';
   // a.percent(10).output(); //不知道小数为啥不对 
    

    return 0;
}

1.17

 一样的(只是换成了一个总额 amount 无需dollars 和cents

见 1.18

1.18

#include<iostream>
using namespace std;
enum signType{plus,minus};
class currency{
   
     public:
       currency (signType theSign= signType::plus,unsigned long theDollars=0,unsigned int theCents = 0); //构造函数  外部定义  诺省初始值--> 则按此默认给
        ~currency(){};//析构函数 为空 
        void setValue(signType,unsigned long,unsigned int ); //原型 定义在class 外部 
        currency add(const currency&) const; //此const表示 不改变参数的内容 
        void output() const;
        void input(); 
        double  subtract(double x);
        currency percent(double x);
        currency mulitiply(double x);
        currency div(double x);
    //--------符号函数  
    currency operator-(currency &) ; //(1)
    currency operator%(currency &); 
    currency operator*(currency&);
    currency operator/(currency&);
    friend istream& operator>>(istream&, currency &); // 友元 不是成员函数也能访问  
    friend ostream& operator<<(ostream&, const currency &) ;



        private :  //只能通过成员函数访问  不能对象私自 访问
          long amount;
}; //最后也要加分号

 currency::currency (signType theSign,unsigned long theDollars,unsigned int theCents){
     setValue(theSign,theDollars,theCents);
}
void currency::setValue(signType Sign,unsigned long Dollars,unsigned Cents){ // 如显示初始化对象 ,则调用此  64row
    //给调用对象 的成员赋值 
     if(Cents >99){
          throw "Max of Cents";
     }
     amount = Dollars*100+ Cents;
      if(Sign== signType::minus)
       amount = -amount;
}

 currency currency::operator-(currency &x) {
       currency result;
       result.amount = amount-x.amount;
       return result; 
 }
 istream& operator>>(istream &in ,currency &x){ // 友元不是成员函数!! 不用加::
      long temp;
      in>>temp ;
         x.amount = temp*100;
      return in;
 }
 ostream& operator<<(ostream& out,const currency &x) {
       long theA=x.amount;
       if(theA <0){
           out<<'-';
           theA = -theA;
       }
         out<<theA/100<<'.'<<theA-theA/100;
         return out;
 }
 currency currency::operator%(currency &x){
      currency result ;
      result.amount = amount%x.amount;
      return result;
 }
 currency currency::operator*(currency &x){
     currency result;
     result.amount = amount*x.amount;
     return result;
 }
 currency currency::operator/(currency &x){
     currency result;
     result.amount = amount/x.amount;
     return result;
 }

 
 
int main(){
   currency a,b;
   cin>>a>>b;
   cout<<a-b;
   
  
   
    

    return 0;
}

1.19

#include<iostream>
using namespace std;
int factorial(int n){
    int result=1;
     while(n>0){
         result *=n--;
     }
      return result;
}
int main(){
    cout<<factorial(5);
    return 0;
}

1.20

#include<iostream>
using namespace std;
int count;
int Fibonacci(int n){
   int f;
    ::count++;
    if(n==0)
        return 0;                            
    else if(n==1||n==2)
        f=1;
    else
        f=Fibonacci(n-1)+Fibonacci(n-2);    
    return f;

}
int fib(int n){
      if(n <=2){
           return 1;
      }
    int f,f1=1,f2=1;
       while(n>2){
            f=f1+f2;
            f2=f1;
            f1=f;
            n--;
       }
       return f;
}

int main(){
    cout<< Fibonacci(5)<<' '<< ::count <<'\n'<<fib(5);
    return 0;
}

1.21

#include<iostream>
using namespace std;
int fun1(int n){
    if(n%2 ==0)
       return n/2;
        else 
          return fun1(3*n+1);
}
int fun2(int n){
    if(n%2 == 0)
       return n/2;
        else 
        return (3*n+1)/2;
}
int main(){
    cout<< fun1(3)<<'\n'<<fun2(3);
    return 0;
}

1.22

#include<iostream>
#include<math.h>
using namespace std;
int Ack(int i,int j){
    if(i ==1&& j>=1){
         return pow(2,j);
    }
     else if( i>=2 && j==1)
       Ack(i-1,2);
       else if(i>=2 && j>=2)
         Ack(i-1,(Ack(i,j-1)) ) ;
         else return 0; 
         
}

int main(){
    cout<<Ack(2,2);
    return 0;
}

1.23

证明:Fibonacci 数列及其计算方法_Ivan 的专栏-CSDN博客_fibonacci数列

#include<iostream>
using namespace std;
int Gcd(int x,int y){
     if(y == 0)
      return x;
        return Gcd(y,x%y);
}

int main(){
    cout<<Gcd(112,42);

    return 0;
    
}

1.24

#include<iostream>
using namespace std;
template<class T>
bool
fun(T* array,T value,int end){
     for( int i=0;i<end;i++){
         if(array[i]== value)
           return true;
     }

     return false;
}
int main(){
    int array[]{25,78,0,666};
    cout<<fun(array,666,4);
    return 0;
}

1.25

类似二叉树分支

 #include<iostream>
 using namespace std;
void Subset(char a[], int n, int len) {
 
	if (n == 0) {  // 递归终止条件
 
		for (int i = 0; i < len; i++) cout << a[i];
		cout << endl;
		delete[] a;  // 这里的a 就是temp
		return;
	}
 
	for (int j = 0; j <= 1; j++) { //每次需要做两种决策
 
		char *temp = new char[len];  
		
		for (int i = 0; i < len; i++) temp[i] = a[i];  //用临时数组来覆盖原来数组
 
		if (j == 0) { 
			temp[n - 1] = '0';
		}else {
			temp[n - 1] = '1'; 
		}
		Subset(temp, n - 1,len);
		
	}
	
}
 
 
int main()
{
	char a[3] = { 'a','b','c'};
	Subset(a, 3,3);
	
    return 0;
}

1.26

#include<iostream>
using namespace std;
void 
GrayCode(int n){
    if(1== n)
       cout<<1;
        else {
            GrayCode(n-1);
            cout<<n;
            GrayCode(n-1);
        }
}

int main(){
    GrayCode(4);
    return 0;
}

1.27

#include<iostream>
using namespace std;
template <class T>
int 
accumulate(T array,int end,int value){
    for(int i =0;i<end ;i++){
        value+=array[i];
    }
    return value;
}
int main(){
    int a[]={1,2,5,3,8};
    cout<< accumulate(a,5,0);

    return 0;
}

1.28

#include<iostream>
using namespace std;
template<class T,class funP>
int 
accumulate(T array,int end ,int result,funP p){
    for(int i=0; i<end;i++){
         result *= p(array,i);
    }

     return result;
}
int 
get_value(int *array,int i){
    return array[i];
}

int main(){
     int array[]={1,5,10,8};
      cout<< accumulate(array,4,1,get_value);
       return 0;
}

1.29

#include<iostream>
using namespace std;
template<class T>
bool
Copy(T a,int n,T b){
     for(int i= 0;i<n;i++){
         b[i]= a[i];
     }
      return true;
}

int main(){
    int a[]= {1,5,7,9,10};
    int b[10];
    if( Copy(a,5,b) ) 
     cout<< b[4];

      return 0;
}

1.30

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a[]={1,2,10};
     sort(a,a+3); //无回调函数 默认升序 
      do{
          cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<endl;
      }while(next_permutation(a,a+3));// next 初始值之后的全排列 

      return 0;

}

1.31

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a[]={2,3,1};
    cout << "next is:"<<endl ;
  do{
          cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<endl;
      }while(next_permutation(a,a+3));// next 初始值之后的全排列 
   cout<< "pre is"<<endl;
     a[0]=2;
     a[1]=3;
     a[2]=1;//恢复初始值
   do{
          cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<endl;
      }while(prev_permutation(a,a+3));
   
   return 0;
}

1.32

#include<iostream>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a[]={2,3,1};
      while(next_permutation(a,a+3));// 直接到底
   do{
          cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<endl;
      }while(next_permutation(a,a+3));// next 初始值之后的全排列  A32
   
}
    
     

1.33

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
     vector<int> a;
        for(int i=0;i<6;i++)
    {
        int temp;
        cin>>temp;
        a.push_back(temp);
    }

     cout<<count(a.begin(),a.end(),6);

     return 0;
}

1.34

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
     int a[10];
      fill(a,a+10,6); //参数应是个迭代器类型(指针)
      for(int i=0;i<10;i++){
          cout<< a[i]<<' ';
      }
      cout<< endl;

      return 0;
}

1.35

#include<numeric> //  inner_product 在此头文件
#include<iostream>
using namespace std;
int main(){
    int a[]={1,2,3,4,5,6};//内积?? 自己跟自己 
    cout<<inner_product(a,a+6,a,0);

    return 0;
}

1.36

#include<iostream>
#include<numeric>
using namespace std;
int main(){
    int a[8];
    iota(a,a+8,6); //初始值 递增 ! 
    for(int i=0;i<8;i++){
        cout<<a[i]<<' ';
    }
    cout<<endl;

    return 0;
}

1.37

#include<iostream>
#include<numeric>
using namespace std;
int main(){
    int a[]={99,8,6,4,2};
    cout<<is_sorted(a,a+5)<< endl;  //若已经增排序 返回true

    return 0;

}

1.38

pair 没学到 不太会 matching返回的是什么?

#include<iostream>
#include<algorithm>
#include <utility>
using namespace std;
int main(){
    int a[]={1,2,3,4,5,6};
    int b[]={1,2,3,4,5,999};
    pair<int *,int *> result;
     result = mismatch(a,a+6,b); //返回不相等的两个元素??
      cout<< *result.first<<' '<<*result.second;

    return 0;
}

1.39

#include<iostream>
using namespace std;
template <class T>
int 
STL_count(T start, T end,int value){
    int result =0;
     for( int i=0; start+i<end;i++){
         if(value == start[i])
             result++;
     }
     return result;
}

int main(){
    int a[]{2,5,7,8,666,8};
    cout<<STL_count(a,a+6,8);
    return 0;
}

1.40

#include<iostream>
using namespace std;
template<class T>
void 
STL_fill(T *start,T* end,T value){
        for(int i =0; start+i<end;i++){
            start[i]= value;
        }
}
int main(){
    int a[9];
    STL_fill(a,a+9,6);
    for(int i =0;i<9;i++){
        cout<<a[i];
    }
}

1.41

#include<iostream>
using namespace std;
template<class T>
T
inner(T *start,T *end,T* start1,T *end1){
     int i=0;
     int result =0;
      while( start+i<end && start1+i <end1){
           result = result + start[i]*start1[i];
           i++;
      }
      return result;
}

int main(){
    int a[]{1,2,4,5,6};
    int b[]{1,2,3};
    cout<< inner(a,a+5,b,b+3);
    return 0;
}

1.42

#include<iostream>
using namespace std;
template<class T>
void 
ioat(T *start,T *end,T value){
    for(int i=0;start+i<end;i++){
         start[i]=value++;
    }

}
int main(){
     int a[10];
     ioat(a,a+10,10);
     for(int i=0;i<10;i++)
      cout<< a[i]<<' ';

      return 0;
}

1.43

#include<iostream>
using namespace std;
template<class T>
bool
is_sorted(T start,T end){
    int i=0;
     while(start+i<end-1){
         if(start[i]>start[i+1])
           return false;
             i++;
     }

     return true;
}

int main(){
    int a[]{1,2,5,8,999};
    cout<< is_sorted(a,a+5);

    return 0;
}

1.44

#include<iostream>//错的 待改
using namespace std;
template<class T>
// 该返回什么????
mismatch(T strart,T end,T strart1){
     int i=0;
      while(strart+i<end){
          if(strart[i] != strart1[i] )
                  return [strart[i],strart1[i]];
                  i++;
      }

      return nullptr;
}

int main(){
    int a[]={1,2,3,4,5,6};
    int b[]={1,2,3,4,5,999};
    pair<int *,int *> result;
     result = mismatch(a,a+6,b); //返回不相等的两个元素??
      cout<< *result.first<<' '<<*result.second;

    return 0;
}

1.45

 因为每一条语句 本身就是从句(无再细分布尔式)

1.46

  {a,3}  

  a={2,4,1}

1.47 

  两条  : 1 2 3? 4

1.48 

n条执行路径(当n固定时 步骤也是固定的 ,递归)

执行的语句条数为 2N+2

     第一章总结:

  c++部分 :

        函数传参:  

                            a 传值 

                            b 传引用  (与指针一样都要临时变量空间

                            c 传指针 

         模板参数: 

      template <class T ,...>

      函数体

          异常 :

             throw 

             try{}

             catch()

       

       动态分配:

                       new

                       delete

      自定义类class

                         构造函数

                         析构函数

                         方法 

                         符号重载 

                         友元(不算成员函数 

       递归

                    归纳 

                     -->基础表达式

     STL (重点

            自带的算法

    

      测试与调试

            重点:测试的目的是为了暴露程序的错误,而不是证明是否正确 

            测试集 :

                           黑盒 : 分结果种类

                           白盒:

                                       语句覆盖:每条语句至少执行一次 

                                       分支覆盖 :程序的每个条件都分别去true 和 false 

                                       从句覆盖: 最小子单元的判断-->从句   

                                       执行路径覆盖: 有可能走的路径 都要经过 ?

                    边界测试:如数组边界时

              

           调试:

                 逻辑推理 

                 必要时重新设计 

                 增量测试

      

                             第二章(时间/空间复杂度)

2.1

 有更多的空间留作他用

 模拟计算程序最大的规模

2.2

 省钱 

 有更大市场 

2.3

 都有可能

2.4

 硬件/编译器/优化/使用的语言 

2.5

 24 4k 8k 2w 24 324

2.6

 12* MAX[n-1,1]

2.7

  非递归n!  S= 0  

   1-29 为8N 

时间

2.8

    v=v*2+C(n-i)

2.9

   r= [2,1,5,4,8]

2.10-2.17 

    略 自己画图很简单

2.18

    2n

2.19

   n-1次 

2.20 

    a={5,4,3,2,1}. 

     只要使a[i] != r[i] 即可 

2.21

(row-1)的平方 

2.22

  就是swap的频率  

   row*(row-1)/2

2.23

   n的三次方

2.24

  n*p*m

2.25

   2*     {(m-k+1)k[1,m]的连加}

2.26

 2*(n-1). 

 n-1 

 下一个性能更好

2.27

  n+1 

  2n+1

2.29

  

#include<iostream>
using namespace std;
void 
fun(int *x,int n){
    int count =0;
      count++ ;
        for(int i=0;i<n;i++){
            count ++;
            x[i]+=2;
        }
        int i=1; count++;
        count ++;
        while(i<n/2){
            x[i] += x[i+1];
            i++;
            count +=2;
        }
        cout<< count <<endl;
}
void 
fun1(int *x,int n){
    int count =0;
      count++ ;
        for(int i=0;i<n;i++){
            count ++;
        }
         int i = 1; count++;
        count ++;
        while(i<n/2){
            i++;
            count +=2;
        }
        cout<< count<<endl;
}
int main(){ 
      int a[]={1,2,43,57,4};

      fun(a,5);
      fun1(a,5);


}

  

2.30 

    (1)- (8) 略 

  (9 :

            最坏: 2n+4 

   (10: 

           最好 :n

           最坏: 3n+n*(n-1)/2  -2

    (11: 

        最好 :3n+1 

        最坏: 3n(n-1)/2 +n+1

   (12: 

         调用函数步数都是一样的 ,关键看被调用里面的函数步数 

           最好:  n+n-1+ (n+3) n=[1,n-1]的累加 

           最坏: n+n-1+ (2n+3) n=[1,n-1]的累加 

    (13:

          最坏:

                 n+2(n-1)+(2+n)(n-1)-1+(n-1)

    (14:

             (2n-1) n=【2,n】 的累加 

      (15:

               (4n-1)n=【2,n】 的累加

   

1.31  

     略 

1.32 

 1):

        (3n+3)/2

  2):   

         (2n+6)/2 

   3): 

      (3n+8)/2

1.33 

 条件一样时可以交换??

1.34 

    2-12: 3/2 *n的平方-1/n-1 

    2-15:  n方+5n-7

    2-13: 2*n方+n-3 

   最坏应该冒泡比较好?

1.35

    不一定吧,因为内存S(q)可能跟特征值没关系 

1.36 

   技巧:算出n不是非基础部分的次数 ,最后一次就是基础部分  

 1) 【n,1】 共n次非基础部分  2*n   + 基础部分 2 

      -->  总 2n+2 

 2) (n-1)/2 +1 

 3)    2n  n[1,n]的累加 

 4) 2的n-1次方 +1 

 5) 3的n-1次方+1  

      第二章总结:

   分为 空间复杂度和时间复杂度 

空间:(变量,常量,返回地址等)

   C+S(n)   : 其中s(n) 是可变的 -->实列特征

   与多种可能有关 

      

       时间:

            编译时间+ 运行时间  

               因为编译时间不受实列特征影响,所以我们注重运行时间  !

       

                   运行时间: 

                                       a 找出关键操作(加法,乘法次数

                                       b 确定总步数 (包括调用,递归等) 

                    B步数:

                           分为最好情况和最坏情况 

                                    平均 == (最坏+最好)/2  因为每一个概率都相等 

                         步数方法: 

                                      1 变量法 设置全局变量写进代码 来++ 

                                       2 剖析法: 

                                                      确定每一条语句的步数 *频率  

小技巧::

    for循环时 :

                         for本身次数 :  如果有边界 [ a,b )    为b-a+1

                                                  如果没有边界 [a,b]      为a-b+2 

                        

                     进入for的次数: 为for本身次数-1   

递归时:

       如果非基础部分易看 , 可以分析出进行非基础部分递归的次数 

         然后加以条件 再加基础部分  

补充: 新算法排序(名次排序) new rank数组 --> 记录下标元素比原数组小的数 +本数左边与其相等的数  。 rank数组的值 就应该是对应的位置   a[r[0]]= a[0] 

                       

  

                                       第三章          

3.1

  统一    p(n)/q(n) ,因为最高次不一样 就会趋于0 

 证明完成 

 3.2

 O().  取最大次项 ,再将系数化为1即可

    

3.3 

  3n+7<3n+n=4n  当c= 8 时 使得g(n) 大于f(n) 

   所以f(n) = O(n). 

  其他一样证 

3.4

 一样 ,取最大项

3.5

  g(n) / f(n)  看是否趋于 0即可 

  或推导 >= 都 c n0 

3.6

  最大次项 

3.7

    Ω(n) <=    f(n) <= O(n) 

    直接找

3.8

    因为多元 :

        小技巧: 如果一个式子是因式,则直接消除 

         如 3mn^2+7m^2n+4mn+8m+2n+16 

               -->后四项都是前面的因式 

      -->  =O(mn^2+m^2)

渐进数学: 难死了 数学还是重要

3.9

 找 n0 c  推出 

3.10

 用两式子相除,得到大于 >=(<=) C   

  注意:Θ 要两边除 得到两边边界。

3.11 

   用定理或定义 推出正确结果 

3.12 

   还真不会 应该是:

    大于等于 (每次少最小一项 ) -->   

     最后>= an^m 

3.13

  反证? 存在 m<n0 使得 g(n) <= c[1,c0]*f(n)

3.14

 反过来不知道怎么证, 后条件只能证明 g(n) 是f(n) 的上界呀 ,

  怎么证明f(n)一定渐进小于g(n) ,不包括等于的情况 

3.15

     纯数学求和 ,建议百度  

 E4,5

这个通项公式是一个非常特别的
公式为
1^k+2^k+...+n^k=((n+1+p)^(k+1)-p^(k+1))/(k+1)
我们先要求一个数字p,p满足以下规则
(1+p)^(k+1)-p^(k+1)=0这个里面首先要展开,展开后对于p,p^2 p^3等,我们要当成一个整体对待,比

E6 

 最大次

E7

放缩法

E8

 lim[1/(n+1)+1/(n+2)+......+1/(n+n)]=lim(1/n)[1/(1+1/n)+1/(1+2/n)+......+1/(1+n/n)]=定积分(上限1,下限0)[1/(1+x)]dx=ln(1+x)(上限1,下限0)=ln(1+1)-ln(1+0)=ln2.

3.16 

  只可意会不可言传 

3.17

  还真不会 

     不过应该往松条件取

3.18

1)    Θ (n)

      Θ (n)

      Θ (n)

      Θ (n^2)

       Θ (n^3)

       Θ (m*p*n)

       Θ (n)

       Θ (n)

       Θ (n)

10)    Θ (n^2)

         Θ (n*n!)

         Θ (n^2)

         Ω(n).    O(n^2)

         Θ   (n^2)

         Ω(n).    O(n^2)    

         Θ (n^2)

17).  Ω(n).    O(n^2)        

3.19

 1) n>100

 2) n>2

 3) n<10

 4) 带数测试 n[2^13,2^14] 中间取到相等 

3.20 

   略 ,乘上倍数就行了

 3.21

   n不同 t(n) 的规模也不同。

     以n== 100 为例子  n的最高次每增加一次 效率是1/100 倍  然后根据x的增加 比较一下即可

      第三章总结:

渐进记忆法:

                      1  O(n)  最小上界

                      2  Ω(n) 最大下届

                      3  Θ(n)  f的上界和下界都是同一个函数的情况 ,C可以不同 

                      4 o(n)  小于上界, f(n) 一定渐进小于 cg(n),不包括等于 

1: 

     定义:  存在 C,n0 ,使得 n>n0 时   f(n) <= C*g(n) 

       a:   g(n) 的类型就是我们通常算时间复杂度的函数类型(如对数阶

       b:  可以通过找C ,g(n) 来确定O(n).  

       c: 通常找最小上界,才有实际意义 

       

      定理:

              f(n) = O(最高次的项) 

              f(n)/g(n) <= C  当且仅当  f(n) = O(g(n) ) 

2.

   定义:  存在 C,n0 ,使得 n>n0 时   f(n) >= C*g(n) 

           a: 这就是下界 ,f(n) 一定渐进大于或等于 cg(n)

           b:通常最大下届取 

  

定理:

              f(n) = O(最高次的项) 

              f(n)/g(n) >= C  当且仅当  f(n) =Ω (g(n) ) 

3.

    定义 : 存在 c1,c2,n0 ,使得n>n0时   c1*g(n) <= f(n) <= c2*g(n)  

                  

   

   定理:

              f(n) = O(最高次的项) 

              假设f(n) 和g(n) 都有极限 f(n)/g(n) 和 g(n)/f(n) 存在 , 当且仅当

   f(n)/g(n)<=c  以及 g(n)/f(n)<= c 存在  

4.

   严格小于c*g(n)

另外:也可以推广到多元函数 :

  任意一元趋于无穷 ,两函数比例为无穷 且 另一元趋于无穷,两函数比例为0

                                  第四章

测试模板::

 

#include<iostream>
#include<time.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义


int main(){
    int a[MAX_];
    int step =10;
    
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
      for(int n= 0;n<= MAX_;n+= step){
             long numberRepetitions =0;
             clock_t startTime= clock();//返回目前为止的时间
            
         do{
             numberRepetitions++;
              //初始化数组for
               
               
              //...调用函数
         }while (clock()- startTime <1000);
          long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           cout<< n <<'\t'<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<endl;
        
          if(n==100)
             step =100;
         
      }
    return 0;
}

但是n到不了1000 会溢出 不知道怎么办

4.1

 因为没有除以 clocksPerMillis ,代表一毫秒 

4.2

#include<iostream>
#include<time.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义  
template<class T>
void insertionSort(T *a,int n){
   for(int i=1;i<n;i++){
     T t=a[i];
     int j;
     for( j=i-1;j>=0 && t<a[j];j--)
       a[j+i]=a[j];
      a[j+i]= t;
   }
}

int main(){
    int a[MAX_];
    int step =10;
    
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字 
      for(int n= 0;n<= MAX_;n+= step){
             long numberRepetitions =0;
             clock_t startTime= clock();//返回目前为止的时间 
            
         do{
             numberRepetitions++;
              //初始化数组for 
               for(int i=0;i<MAX_;i++)
                  a[i]=100-i;//逆序 也可以顺序就是最好情况
               
              //...调用函数 
                  insertionSort(a,n);
         }while (clock()- startTime <1000);
          long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           cout<< n <<'\t'<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<endl;
        
          if(n==100) 
             step =100;
         
      }
    return 0;
}

          可以看到如果是最好情况,是线性增长的 说明O(n)

  最坏:不是线性的 n不够大导致不是很明显 O(n^2)

   

  所以2-15的程序好一点 ,最好情况是n 而2-14 都是n^2

4.3

   

#include<iostream>
#include<time.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义
template<class T>
void 
bubbleSort1(T *a,int n){
    for(int i=n;i>1;i--){
        for(int j=0;j<n-1;j++)
           if(a[j]>a[j+1])
              swap(a[j],a[j+1]);
    }
}
template<class T>
void 
bubbleSort2(T *a,int n){
     bool swapped = true;
    for(int i=n;i>1 &&swapped ;i--){
       swapped = false;
        for(int j=0;j<i;j++)
         if(a[j]>a[j+1]){
              swap(a[j],a[j+1]);
              swapped = true;
         }
    }
}


int main(){
    int a[MAX_];
    int step =10;
    
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
      for(int n= 0;n<= MAX_;n+= step){
             long numberRepetitions =0;
             clock_t startTime= clock();//返回目前为止的时间
            
         do{
             numberRepetitions++;
              //初始化数组for
                  for(int i=0;i<MAX_;i++)
                    a[i]=100-i;
               
              //...调用函数
              bubbleSort1(a,n);
         }while (clock()- startTime <1000);
         long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           clock_t startTime2= clock();
           do{
                bubbleSort2(a,n);
           }while (clock()- startTime2 <1000);
          long double elapsedMillis2= (clock()-startTime2)/clocksPerMillis;
           cout<< n <<'\t'<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<' '
           <<elapsedMillis2/numberRepetitions
           <<endl;
        
          if(n==100)
             step =100;
         
      }
    return 0;
}

可以看到结果

 说明最坏情况下(逆序,每两个比较都要交换) 性能基本一致

4.4/5 

  略 思路基本一致 

4.6 

  正确形式应该如4.7

#include<iostream>
#include<time.h>
#include<stdlib.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义  
template<class T>
void insertionSort(T *a,int n){
   for(int i=1;i<n;i++){
     T t=a[i];
     int j;
     for( j=i-1;j>=0 && t<a[j];j--)
       a[j+i]=a[j];
      a[j+i]= t;
   }
}

int main(){
    time_t t;
    srand(time(&t));//时间作为随机数种子
    int a[MAX_];
    
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字 
      for(int n= 0;n<10;n++){
             long numberRepetitions =0;
             clock_t startTime= clock();//返回目前为止的时间 
            for(int i=0;i<MAX_;i++)
                  a[i]=rand()%65535; //每一次循环产生随机数列
    
         do{
             numberRepetitions++;
            
                  insertionSort(a,n);
         }while (clock()- startTime <10);
          long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           cout<< n <<'\t'<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<endl;
        
       
         
      }
    return 0;
}

固定排列数为1k 结果:

       

 感觉平均时间是O(n)

4.7

#include<iostream>
#include<time.h>
#include<stdlib.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义
template<class T>
void 
bubbleSort1(T *a,int n){
    for(int i=n;i>1;i--){
        for(int j=0;j<n-1;j++)
           if(a[j]>a[j+1])
              swap(a[j],a[j+1]);
    }
}
template<class T>
void 
bubbleSort2(T *a,int n){
     bool swapped = true;
    for(int i=n;i>1 &&swapped ;i--){
       swapped = false;
        for(int j=0;j<i;j++)
         if(a[j]>a[j+1]){
              swap(a[j],a[j+1]);
              swapped = true;
         }
    }
}


int main(){
    int a[MAX_];
    int step =10;
    time_t t;
    srand((unsigned)time(&t));
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
    int count =0;
    while(count<20){
          for(int i=0;i<MAX_;i++)
                a[i]= rand()%65535;
    
      for(int n=0;n<= MAX_;n+= 200){
             long numberRepetitions =0;
             clock_t startTime= clock();//返回目前为止的时间
            
         do{
             numberRepetitions++;
               
              //...调用函数
              bubbleSort1(a,n);
         }while (clock()- startTime <1000);
         long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           clock_t startTime2= clock();
           do{
                bubbleSort2(a,n);
           }while (clock()- startTime2 <1000);
          long double elapsedMillis2= (clock()-startTime2)/clocksPerMillis;
           cout<< n <<'\t'<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<' '
           <<elapsedMillis2/numberRepetitions
           <<endl;
        
         
      }
       cout<<"new rand row:"<<endl;
      count++;
    }
    return 0;
}

结果:

 明显终止冒泡平均优于普通的

4.8/9 

  略 思路一样 

4.10

      

#include<iostream>
#include<time.h>
#include<stdlib.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义
template<class T>
int 
sequntialSearch(int *a,int n,const T& x){
    int i;
     for(i=0;i<n&& a[i]!=x;i++)
              ;
       if(i==n) return -1;
         else return i;
}
template<class T>
int 
binarySearch(T *a,int n,const T&x){
    int left =0;
    int right=n-1;
    while(left <=right){
        int mid= (left+right)/2;
        if(x== a[mid]) return mid;
        if( x>a[mid]) left=mid+1;
         else right=mid-1;
    }
    return -1;

}


int main(){
    int a[MAX_];
     for(int i=0;i<MAX_;i++)
                a[i]= i;
    time_t t;
    srand((unsigned)time(&t));
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
    int count =0;
    while(count<20){
         int temp= rand()%MAX_;//使每个被查找概率相等
             long numberRepetitions =0;
             long number2=0;
             clock_t startTime= clock();
            
         do{
             numberRepetitions++;
               
              sequntialSearch(a,MAX_,temp);
         }while (clock()- startTime <1000);
         long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           clock_t startTime2= clock();
           do{
               number2++;
               binarySearch(a,MAX_,temp);
           }while (clock()- startTime2 <1000);
          long double elapsedMillis2= (clock()-startTime2)/clocksPerMillis;
           cout<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<' '
           <<number2<<' '
           <<elapsedMillis2/number2
           <<endl;
         cout<<"new rand row:"<<endl;
       count++;
         
      }
        return 0;
}
    
    
  

      

结果:

折半查找明显好于 顺序查找!

4.11

最坏情况:查找元素为最后一个

#include<iostream>
#include<time.h>
#include<stdlib.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义
template<class T>
int 
sequntialSearch(int *a,int n,const T& x){
    int i;
     for(i=0;i<n&& a[i]!=x;i++)
              ;
       if(i==n) return -1;
         else return i;
}
template<class T>
int 
binarySearch(T *a,int n,const T&x){
    int left =0;
    int right=n-1;
    while(left <=right){
        int mid= (left+right)/2;
        if(x== a[mid]) return mid;
        if( x>a[mid]) left=mid+1;
         else right=mid-1;
    }
    return -1;

}


int main(){
    int a[MAX_];
     for(int i=0;i<MAX_;i++)
                a[i]= i;
    time_t t;
    srand((unsigned)time(&t));
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
    int count =0;
    
             long numberRepetitions =0;
             long number2=0;
             clock_t startTime= clock();
            
         do{
             numberRepetitions++;
               
              sequntialSearch(a,MAX_,999);//最后一个时为最坏
         }while (clock()- startTime <1000);
         long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           clock_t startTime2= clock();
           do{
               number2++;
               binarySearch(a,MAX_,999);
           }while (clock()- startTime2 <1000);
          long double elapsedMillis2= (clock()-startTime2)/clocksPerMillis;
           cout<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<' '
           <<number2<<' '
           <<elapsedMillis2/number2
           <<endl;
     
        return 0;
}
    
    
  

结果:

   高下立判

4.12

4.13 

#include<iostream>
#include<time.h>
#include<stdlib.h>
#include<algorithm>
#define MAX_ 1000
using namespace std;
// 测试的函数定义
template<class T>
void insertionSort(T *a,int n){
   for(int i=1;i<n;i++){
     T t=a[i];
     int j;
     for( j=i-1;j>=0 && t<a[j];j--)
       a[j+i]=a[j];
      a[j+i]= t;
   }
}


int main(){
    int a[MAX_];
    int step =10;
    time_t t;
    srand((unsigned)time(&t));
   long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
    int count =0;
    //初始化数组 (最好 or最坏
     for(int i=0;i<MAX_;i++)
        a[i]= i;
          
    
      for(int n=0;n<= MAX_;n+= step){
             long numberRepetitions =0;
             clock_t startTime= clock();//返回目前为止的时间
            
         do{
             numberRepetitions++;
               
              //...调用函数
              insertionSort(a,n);
         }while (clock()- startTime <1000);
         long double elapsedMillis= (clock()-startTime)/clocksPerMillis;
           clock_t startTime2= clock();
           do{
                sort(a,a+n);
           }while (clock()- startTime2 <1000);
          long double elapsedMillis2= (clock()-startTime2)/clocksPerMillis;
           cout<< n <<'\t'<< numberRepetitions <<'\t'<< elapsedMillis/numberRepetitions<<' '
           <<elapsedMillis2/numberRepetitions
           <<endl;
        if(100 == n)
            step =100;
    }
    return 0;
}

最好结果:

最坏结果:

  

感觉两个运行时间差不多,性能差不多?

4.14/15

略 

4.16

4.17

#include<iostream>
#include<algorithm>
using namespace std;

void 
TransposeMatri(int **array,int n){
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++){
            if(j>i)//主副三角
              swap(array[i][j],array[j][i]);   
      }
}
void 
matrixMultiplication(int **a,int **b,int **c,int n){
     TransposeMatri(b,n);//先转置
      for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
             int sum =0;
              for(int k=0;k<n;k++)
                 sum+=a[i][k]* b[j][k];//4.2公式
                c[i][j]= sum;
        }
}
int main(){
    int **a= new int *[2];
     for(int i=0;i<2;i++)
        a[i]=new int [2];
        a[0][0]=1; a[0][1]=2;a[1][0]=3;a[1][1]=4;
        int **b= new int *[2];
     for(int i=0;i<2;i++)
        b[i]=new int [2];
        b[0][0]=1; b[0][1]=2;b[1][0]=3;b[1][1]=4;
             
     int **c= new int *[2];
     for(int i=0;i<2;i++)
        c[i]=new int [2];
    matrixMultiplication(a,b,c,2);
       for(int i=0;i<2;i++){
             for(int j=0;j<2;j++)
             cout<<c[i][j]<<' ';
          cout<<endl;
       }
       
     
    return 0;
}

4.18

(1条消息) C++性能优化系列——矩阵转置(二)循环分块优化缓存访问_yan31415的博客-CSDN博客

自己写的有误,最远处的对角并没有互换,思路错了 

#include <algorithm>
#include <iostream>

using namespace std;

void TransposeMatri(int **array, int n) { //全部转置
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++) {
            if(j > i) //主副三角
                //swap(array[i][j], array[j][i]);
                swap((*(int (*)[n][n])(array))[i][j], (*(int (*)[n][n])(array))[j][i]);
        }
}

void Block_transpose(int **array, int n) { //分块转置
    /*
    int k = 2;
    for(int i = 0; i < n; i += k)
        for(int j = 0; j < n; j += k)
            TransposeMatri((int **)((int *)array + i * n + j), k);
    */
    int k = 2;
    for(int i = 0; i < n; i += k)
        for(int j = 0; j < n; j += k) {
            int a[k][k];
            for(int y = 0; y < k; ++y) {
                for(int x = 0; x < k; ++x) {
                    a[y][x] = (*(int (*)[n][n])array)[i + y][j + x];
                }
            }
            //TransposeMatri((int **)((int *)array + i * n + j), k);
            TransposeMatri((int **)a, k);
            for(int y = 0; y < k; 
  • 24
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值