目录

第一章

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

第三章

第四章

第五章

第六章

第七章

第八章

第九章

第十章

第十一章

第十二章


有不正确请提出

                                 第一章

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];} //initfor (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);//3currency 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;elsef=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 就是tempreturn;}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;  //若已经增排序 返回truereturn 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++;//初始化数组forfor(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; ++y) {for(int x = 0; x < k; ++x) {(*(int (*)[n][n])array)[i + y][j + x] = a[y][x];}}}
}int main() {/*int **a = new int *[4];for(int i = 0; i < 4; i++)a[i] = new int[4];*/int a[4][4];for(int i = 0; i < 4; i++) {for(int j = 0; j < 4; j++) {a[i][j] = i * 4 + j;}}for(int i = 0; i < 4; i++) {for(int j = 0; j < 4; j++)cout << a[i][j] << ' ';cout << endl;}//Block_transpose(a, 4);Block_transpose((int **)a, 4);cout << "---------------------" << endl;/*for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++)cout << a[i][j] << ' ';cout << endl;*/for(int i = 0; i < 4; i++) {for(int j = 0; j < 4; j++)cout << a[i][j] << ' ';cout << endl;}/*// 释放一定要写,不写释放的代码在一些环境下会报错的for(int i = 0; i < 4; i++)delete[] a[i];delete[] a;*/return 0;
}

第四章总结

性能测试:

可以通过程序来测量运行所用的时间 clock()

1.可以设置n的数量

2.设置数组的好坏

来模拟最好(坏)的情况 时间随n的增长;一般数字大时才明显O()

缓存(访问模式)对性能(时间)的影响

分为 :

寄存器,L1,L2,主存 等 ,每一个传输周期都会增长很多 ,如果缓存为命中,到下一      级  去找,花费更多时间

如数组的行是线性存放的,很有可能在一个缓存等级中,而列可能相隔很远,在下一个缓存等     级中,将花费更多时间 (矩阵的相乘,ijk->ikj 书p89);

第五章

注意::

copy(start+index,end,start)  --> 访问的就是 start[index] 这个元素

第一个参数是头指针,第二个参数是尾后指针 ,第三个是目的地头指针

arraylist(总)

#include<iostream>
#include<iterator>
#include<algorithm>
using namespace std;template<class T> // 抽象类 相当于提供接口?  派生类定义这些函数?
class linearList{//都是纯虚函数public:virtual ~linearList(){};virtual bool empty() const =0;// virtual int size()const =0;// virtual T& get(int theIndex) const =0;// virtual int indexOF(const T& theElement) const = 0;// virtual void erase(int index) =0;// virtual void insert(int theIndex,const T& theElment) = 0;virtual void output(ostream &out) const =0;
};
template<class T>
class arrayList:public linearList<T> //从抽象类派生出的具体类(必须全部实现基类的函数才算)
{public:arrayList(int initCapacity =10); //构造函数arrayList(const arrayList<T>&);  //赋值函数arrayList(const arrayList<T>&,const int ReInit = 0);~arrayList(){delete [] element;}//ADT 抽象类本身带的bool empty() const {return listSize == 0;}//1int size() const {return listSize ;} //1int lenth()const{ return arrayLength;}//1T& get(int theIndex) const;//0int indexOF(const T& theElment) const;void erase(int theIndex);void insert(int theIndex,const T& theElement);void output(ostream & out) const;void setSize(int newSize);void leftShift(int i);//左移iT substitution(int index ,T value );//置换indexvoid merge(arrayList<T>& ,arrayList<T>&);void split(arrayList<T>& ,arrayList<T>&);void ChangeArray();void SetChange(int ALength);void trimToSize();//5.5void swap(arrayList<T>& );void reverse();//翻转线性表void meld(arrayList<T>& ,arrayList<T>&);//合并新链表到调用对象void clear();//使线性表为空void removeRange(int start,int end);//删除索引范围内的所有元素int lastInexOf(T TheElement);//返回出现的最后索引,若无返回-1void circularShift(int i);//循环左移//派生类还可以自己添加方法void half();//隔一个删一个void push_back(T theElement);void pop_back();int capacity() const{return arrayLength; }T& operator[](unsigned index); //返回& 就能作为左值bool operator==(const arrayList<T>& x)const ;bool operator!=(const arrayList<T>& x) const{    bool result = (*this)==x;   return !result;  }bool operator<(const arrayList<T>& x) const;
// 成员也能是类 --》 迭代器class iterator;iterator begin(){return iterator(element);}iterator end(){return iterator(element+listSize);}friend ostream& operator<<(ostream &out,const arrayList<T>& x){ //把友元函数体放到类声明内部,使其跟着类的实例化一同实例化:x.output(out);return out;}protected://保护成员 不是私有成员 ©️函数能直接访问?bool checkIndex(int theIndex) const;T *element;int arrayLength;int listSize;};
template<class T>
class iterator{public:typedef bidirectional_iterator_tag iterator_category;typedef T value_type;typedef ptrdiff_t difference_type;typedef T* pointer;typedef T& reference;iterator(T* theposition = 0){ position = theposition;}T& operator*() const {return *position;}T* operator->() const{return &*position;}iterator& operator++(){++position ;return *this;}iterator operator++(int){iterator old= *this; ++position; return old;}iterator& operator--(){--position;return *this;}iterator operator--(int){iterator old = *this; --position;return old;}iterator operator+=(int i){position+= i;return *this;}iterator operator-=(int i){position-= i;return *this;}bool operator!=(const iterator right) const{ return position!= right.position;}bool operator==(const iterator right) const{ return position== right.position;}protected:T* position;
}    ;
template<class T>
arrayList<T>::arrayList(int initCapacity ){if( initCapacity<1){cout<< "must > 0";exit(1);}arrayLength = initCapacity;listSize =0;element = new T[initCapacity];
}
template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList){arrayLength = theList.arrayLength;listSize = theList.listSize;element = new T[arrayLength];copy(theList.element,theList.element+arrayLength,element);//前两个是范围 最后一个参数是目的地}
template<class T>
arrayList<T>:: arrayList(const arrayList<T>& x,const int ReInit){//x 满了 就构造一个 新指定数组?T *temp;if(x.listSize == x.arrayLength){if(ReInit == 0){//没指定 默认翻倍arrayLength = x.arrayLength*2;temp = new T[arrayLength];listSize = x.listSize;copy(x.element,x.element+x.listSize,element);delete [] x.element;}else {arrayLength = ReInit;temp = new T[arrayLength];listSize = x.listSize;copy(x.element,x.element+x.listSize,element);delete [] x.element;}}}
template<class T>
bool
arrayList<T>::checkIndex(int theIndex) const{//确定索引是否合法if(theIndex<0 || theIndex>= arrayLength){cout<< "Cross the border"<<endl;return false;}return true;}
template<class T>
void
arrayList<T>::output(ostream & out) const{copy(element,element+listSize,ostream_iterator<T>(cout,"  "));//0
}
template<class T>voidarrayList<T>:: insert(int theIndex,const T& theElement){if ( checkIndex(theIndex)==0 ) {exit(1);}if(listSize == arrayLength){ChangeArray();}copy_backward(element+ theIndex,element+ listSize,element+ listSize+1) ;// 尾部对尾部element[theIndex]= theElement;listSize++;}template<class T>voidarrayList<T>::setSize(int newSize){while(newSize<listSize){element[--listSize].~T();//析构函数}}template<class T>voidarrayList<T>::erase(int theIndex){checkIndex(theIndex);copy(element+theIndex+1,element+listSize+1,element+theIndex);//就是当前元素就行了 a【index】element[--listSize].~T();//析构函数if(listSize<=arrayLength/4){SetChange(arrayLength/2>10?arrayLength/2:10);}}template<class T>voidarrayList<T>::trimToSize(){T *temp = new T [listSize];copy(element,element+listSize-1,temp);//复杂度 O(listsize)delete [] element;arrayLength = listSize;element = temp;}
template<class T>
T&
arrayList<T>::operator[](unsigned index){ //返回& 就能作为左值checkIndex(index);return  element[index];}
template<class T>
bool
arrayList<T>:: operator==(const arrayList<T>& x)const {if(listSize == x.listSize){for(int i=0;i<listSize;i++){if(element[i]!=x.element[i])return false;}return true;}return false;}
template<class T>
bool
arrayList<T>:: operator<(const arrayList<T>& x) const{for(int i=0;i<listSize&& i<x.listSize;i++){if(element[i]<x.element[i])return true;else if(element[i]> x.element[i])return false;}return false;
}
template<class T>
void
arrayList<T>::ChangeArray(){T *temp = new T [arrayLength*2];copy(element,element+listSize-1,temp);//复杂度 O(listsize)delete [] element;arrayLength = listSize*2;element = temp;
}
template<class T>
void
arrayList<T>:: SetChange(int Asize){T *temp = new T [Asize];copy(element,element+listSize+1,temp);//复杂度 O(listsize)delete [] element;arrayLength = Asize;element = temp;
}template<class T>
void
arrayList<T>::push_back(T theElement){if(listSize == arrayLength)ChangeArray();//默认翻两倍//第三个参数copy_backward(element+arrayLength-listSize,element+arrayLength,element+arrayLength-1);//第二个尾部迭代器element[arrayLength-1]=theElement;listSize++;
}
template<class T>
void
arrayList<T>::pop_back(){if(empty()){cout<<"error"<<endl;exit(1);}copy_backward(element+arrayLength-listSize,element+arrayLength,element+arrayLength+1);listSize--;}
template<class T>
void
arrayList<T>::swap(arrayList<T>& x){int i =0;arrayLength>x.arrayLength? x.setSize(arrayLength):setSize(x.arrayLength); //同长while (i<arrayLength&&i<x.arrayLength){T temp = element[i];element[i]=x.element[i];x.element[i]= temp;i++;}int temp= listSize;listSize = x.listSize;x.listSize= temp;}template<class T>
T
arrayList<T>::substitution(int Index,T theElement){T temp = element[Index];element[Index]= theElement;return temp;
}
template<class T>
void
arrayList<T>::clear(){listSize =0;
}
template<class T>
void
arrayList<T>::removeRange(int startIndex,int endIndex){checkIndex(endIndex);checkIndex(startIndex);copy(element+endIndex+1,element+listSize,element+startIndex);listSize -= endIndex-startIndex+1;}
template<class T>
int
arrayList<T>::lastInexOf(T value){int index=-1;for( int i=0;i<listSize;i++){if(value == element[i])index = i;}return index;
}
template<class T>
void
arrayList<T>::reverse(){if(empty() )exit(1);int end = listSize-1;int start = 0;while(start<end){T temp = element[start];element[start] = element[end];element[end] = temp;start++;end--;}
}
template<class T>
voidreverse( arrayList<T> & x){x.reverse();
}
template<class T>
void
arrayList<T>::leftShift(int i){copy(element+i,element+listSize,element);listSize -= i;
}
template<class T>
void
arrayList<T>::circularShift(int i){T *temp= new T[i];copy(element,element+i,temp);copy(element+i,element+listSize,element);//1copy(temp,temp+i,element+listSize-i);delete [] temp;
}
template<class T>
void
arrayList<T>::half(){bool flag =false;for(int i=0; i<listSize;i++){if(flag){copy(element+i+1,element+listSize,element+i);listSize--;flag=false;}flag = true;}
}
template<class T>
void
arrayList<T>::meld(arrayList<T>& a,arrayList<T>& b){if(this->arrayLength<a.listSize+b.listSize)this->SetChange(a.listSize+b.listSize); //不够扩充调用数组int i=0, k=0;for(;i<a.listSize&& i<b.listSize;i++){element[k++]=a.element[i];element[k++]=a.element[i];}if(i<a.listSize)element[k++]=a.element[i++];if(i<b.listSize)element[k++]=b.element[i++];listSize = k;
}
template<class T>
void
arrayList<T>::merge(arrayList<T> &a, arrayList<T> &b){if(this->arrayLength<a.listSize+b.listSize)//a b 已经有序this->SetChange(a.listSize+b.listSize); //不够扩充调用数组int i=0,j=0,k=0;while(a.listSize&& j<b.listSize){if(a.element[i]<=b.element[j])element[k++]=a.element[i++];else element[k++]=a.element[j++];}if(i<a.listSize){element[k++] = a.element[i++];}if(j<b.listSize)element[k++]=b.element[j++];listSize = k;}
template<class T>
void
arrayList<T>::split(arrayList<T> &a, arrayList<T> &b){int i=0,j=0;for(int k=0;k<this->size();k++){if(k%2 == 0)a.element[i++]= element[k];else b.element[j++]= element[k];}a.listSize = i;b.listSize = j;
}
int main(){arrayList<int> a(10),b(10),c(10);//return 0;}

5.1

看描述说明就行

对应的成员函数是什么功能

5.2

size ==2 ;

5.3

前面好像写过,略

5.4

没明白题目意思

template<class T>
arrayList<T>:: arrayList(const arrayList<T>& x,const int ReInit){//x 满了 就构造一个 新指定数组?T *temp;if(x.listSize == x.arrayLength){if(ReInit == 0){//没指定 默认翻倍 arrayLength = x.arrayLength*2;temp = new T[arrayLength];listSize = x.listSize;copy(x.element,x.element+x.listSize,element);delete [] x.element;}else {arrayLength = ReInit;temp = new T[arrayLength];listSize = x.listSize;copy(x.element,x.element+x.listSize,element);delete [] x.element;}}}

5.5

template<class T>void arrayList<T>::trimToSize(){T *temp = new T [listSize];copy(element,element+listSize-1,temp);//复杂度 O(listsize)delete [] element;arrayLength = listSize;element = temp;}

5.6

O(newSize)

要调用析构函数吗??

template<class T>void arrayList<T>::setSize(int newSize){while(newSize<listSize){element[--listSize].~T();//析构函数}}

5.7

T& operator[](unsigned index){ //返回& 就能作为左值checkIndex(index);return  element[index];}

5.8

bool operator==(const arrayList<T>& x)const {if(listSize == x.listSize){for(int i=0;i<listSize;i++){if(element[i]!=x.element[i])return false;}return true;}return false;}

5.9

 bool operator!=(const arrayList<T>& x) const{bool result = (*this)==x;return !result;}

5.10

template<class T>
bool
arrayList<T>:: operator<(const arrayList<T>& x) const{for(int i=0;i<listSize&& i<x.listSize;i++){if(element[i]<x.element[i])return true;else if(element[i]> x.element[i])return false;}return false;
}

5.11.12

template<class T>
void
arrayList<T>::push_back(T theElement){if(listSize == arrayLength)ChangeArray();//默认翻两倍 //第三个参数 copy_backward(element+arrayLength-listSize,element+arrayLength,element+arrayLength-1);//第二个尾部迭代器element[arrayLength-1]=theElement;listSize++;
}
template<class T>
void
arrayList<T>::pop_back(){if(empty()){cout<<"error"<<endl;exit(1);}copy_backward(element+arrayLength-listSize,element+arrayLength,element+arrayLength+1);listSize--;}

5.13

template<class T>
void
arrayList<T>::swap(arrayList<T>& x){int i =0;arrayLength>x.arrayLength? x.setSize(arrayLength):setSize(x.arrayLength); //同长while (i<arrayLength&&i<x.arrayLength){T temp = element[i];element[i]=x.element[i];x.element[i]= temp;i++;}int temp= listSize;listSize = x.listSize;x.listSize= temp;}
template<class T>
void
arrayList<T>:: SetChange(int Asize){T *temp = new T [Asize];copy(element,element+listSize+1,temp);delete [] element;arrayLength = Asize;element = temp;
}

O(arrayLength)   因为不知道是怎么储存的,只能复制整个数组

5.14

就是上一题的 SetChange()

5.15

template<class T>
T
arrayList<T>::substitution(int Index,T theElement){T temp = element[Index];element[Index]= theElement;return temp;
}

5.16

template<class T>
void
arrayList<T>::clear(){listSize =0;
}

O(1)  不需要删除

5.17

template<class T>
void
arrayList<T>::removeRange(int startIndex,int endIndex){checkIndex(endIndex);checkIndex(startIndex);copy(element+endIndex+1,element+listSize,element+startIndex);listSize -= endIndex-startIndex+1;}

O(end-start);

5.18

template<class T>
int
arrayList<T>::lastInexOf(T value){int index=-1;for( int i=0;i<listSize;i++){if(value == element[i])index = i;}return index;
}

O(listSize)

5.19

5.20

 template<class T>void arrayList<T>::erase(int theIndex){checkIndex(theIndex);copy(element+theIndex+1,element+listSize+1,element+theIndex);//就是当前元素就行了 a【index】element[--listSize].~T();//析构函数 if(listSize<=arrayLength/4){SetChange(arrayLength/2>10?arrayLength/2:10);}}

删除:减半数组可能    增加:可能倍增数组

道理应该一样的

5.21

略,不好解释

5.22

template<class T>
void
arrayList<T>::reverse(){int end = listSize-1;int start = 0;while(start<end){T temp = element[start];element[start] = element[end];element[end] = temp;start++;end--;}
}

2) O(listSize)   是listSize的一半

3) {空集} {1} {1,2,3}

4)

template<class T>
voidreverse( arrayList<T> & x){x.reverse();
}

5) 一样的 O(listSize)

6) 应该是对象直接调用性能好 而不是多一层函数调用

5.23

template<class T>
void
arrayList<T>::leftShift(int i){copy(element+i,element+listSize,element);listSize -= i;
}

O(n)

5.24

template<class T>
void
arrayList<T>::circularShift(int i){T *temp= new T[i];copy(element,element+i,temp);copy(element+i,element+listSize,element);//1copy(temp,temp+i,element+listSize-i);delete [] temp;
}

创建一个新数组,暂时保存  然后移到末尾

O(n)

5.25

template<class T>
void
arrayList<T>::half(){bool flag =false;for(int i=0; i<listSize;i++){if(flag){copy(element+i+1,element+listSize,element+i);listSize--;flag=false;}flag = true;}
}

我这应该为O(n^2) ,原地

应该创建一个新数组复制过去

5.26

调用erase,略

5.27

c++ 不太会 到时候再补

iterator& operator+=(int i){position+= i;return *this;}iterator& operator-=(int i){position-= i;return *this;}

还有+ /-  等

STL 之随机访问迭代器_ Yours风之恋 ~~~~~-CSDN博客_随机访问迭代器

5.28

template<class T>
void
arrayList<T>::meld(arrayList<T>& a,arrayList<T>& b){if(this->arrayLength<a.listSize+b.listSize)this->SetChange(a.listSize+b.listSize); //不够扩充调用数组int i=0, k=0;for(;i<a.listSize&& i<b.listSize;i++){element[k++]=a.element[i];element[k++]=a.element[i];}if(i<a.listSize)element[k++]=a.element[i++];if(i<b.listSize)element[k++]=b.element[i++];listSize = k;
}

很容易证明 O(a.listSize+b.listSize)

5.29

template<class T>
void
arrayList<T>::merge(arrayList<T> &a, arrayList<T> &b){if(this->arrayLength<a.listSize+b.listSize)//a b 已经有序this->SetChange(a.listSize+b.listSize); //不够扩充调用数组int i=0,j=0,k=0;while(a.listSize&& j<b.listSize){if(a.element[i]<=b.element[j])element[k++]=a.element[i++];else element[k++]=a.element[j++];}if(i<a.listSize){element[k++] = a.element[i++];}if(j<b.listSize)element[k++]=b.element[j++];listSize = k;}
int main(){arrayList<int> a(10),b(10),c(10);cout<<c.size()<<endl;for(int i=0;i<5;i++){a.insert(i,i+1);b.insert(i,i);}for(int i = 0;i <a.size();i++){cout<<a[i]<<' ';}cout<<endl;for(int i = 0;i <b.size();i++){cout<<b[i]<<' ';}cout<<endl<<"              "<<endl;c.merge(a,b);cout<<c.size()<<endl;for(int i = 0;i <c.size();i++){cout<<c[i]<<' ';}cout<<endl;return 0;}

复杂度O(n)

5.30

template<class T>
void
arrayList<T>::split(arrayList<T> &a, arrayList<T> &b){int i=0,j=0;for(int k=0;k<this->size();k++){if(k%2 == 0)a.element[i++]= element[k];else b.element[j++]= element[k];}a.listSize = i;b.listSize = j;
}

O(size)

5.31

#include<iostream>
#include <iterator>
using namespace std;
template<class T>
class circularArrayList{public:circularArrayList(int init =10);~circularArrayList(){ delete []element;}void erase(int index);void insert(T ElementValue);T& operator[](unsigned index); //返回& 就能作为左值friend ostream& operator<<(ostream &out,const circularArrayList<T>& x){ //把友元函数体放到类声明内部,使其跟着类的实例化一同实例化:x.output(out);return out;}void output(ostream & out) const{copy(element,element+arraylist,ostream_iterator<T>(cout,"  "));}int lenth()const{ return arrayLength;}int getEND()const {return end;}protected://保护成员 不是私有成员 函数能直接访问?T *element;int arrayLength;int start;int end;int arraylist;
};
template<class T>
circularArrayList<T>::circularArrayList(int init){element = new T[init];start = init-1;//下标 向右端储存end=init-2;arrayLength = init;arraylist =0;
}
template<class T>
void
circularArrayList<T>::erase(int index){if(index>=start && index<arrayLength){//在右半边copy(element+index+1,element+arrayLength,element+index);if(end <start){//循环了element[arrayLength-1] = element[0];copy(element+1,element+end,element);}}else if(index<start){copy(element+index+1,element+end+1,element+index);}end= end-1<0?arrayLength-1: end-1;}template<class T>
void
circularArrayList<T>::insert(T value){if(arraylist == arrayLength){;//倍增}end=(end+1)%arrayLength;element[end]=value;arraylist++;}
template<class T>
T&
circularArrayList<T>::operator[](unsigned index){ //返回& 就能作为左值return  element[index];}
int main(){circularArrayList<int> a(10);for(int i=0; i<10;i++)a.insert(i+1);for(int i = 0;i <a.lenth();i++)cout<<a[i]<<' ';a.erase(1);cout<<endl;for(int i = 0;i <a.lenth();i++)cout<<a[i]<<' ';cout<<endl;return 0;}

5.32

应该跟书上差不多 只不过下标循环

5.32-5.36

略,思路跟差不多

只是 下标的表达不同

vectorList

5.37

template<class T>
void
verctorList<T>::half(){bool flag =false;for(int i=0;i<size();i++ ){if(flag){erase(element+i);flag=false;}flag = true;}
}

5.37 , 38

template<class T>
void
verctorList<T>::merge(vector<T>& a,vector<T> & b){if(element->size<a.size()+b.size() )element->resize(a.size()+b.size());int i=0,j=0,k=0;while( i<a.size()&& j<b.size() ){if(a[i]<=b[j])(*element)[k++]=a[i++];else (*element)[k++]=a[j++];}if(i<a.listSize){(*element)[k++] = a[i++];}if(j<b.listSize)(*element)[k++]=b[j++];}

e. vector 对象下标运算符可以访问已存在的元素,而不能用于添加元素

应该用insert

5.40

template<class T>
void
verctorList<T>::split(vector<T>& a,vector<T> & b){int i=0,j=0;for(int k=0;k<this->size();k++){if(k%2 == 0)a[i++]= (*element)[k];else b[j++]= (*element)[k];}}

自行测试。。

5.41 -43

应该还有错误

#include<iostream>
using namespace std;
#define MaxSize 100
#define Type int
#define MAXList 20
Type Array[MaxSize];
Type  *lastA[MAXList];//M个表  指针数组
Type *frontA[MAXList];
int count;
bool Move_forward(int ListNum);//移动到上一个尾部
bool Move_backward(int ListNum);
template<class T>
class MultipleTable{public:MultipleTable(int start=0);void insert(T value);void erase(int index);T* front;T* last;int ListNum;};
template<class T>
MultipleTable<T>::MultipleTable(int start){if( start>=MaxSize || (count>0 && start <= *frontA[count-1] ) ) {//如果不是第一个表 且 front【i】 < last[i-1]cout<<"error "<<endl;exit(1);}ListNum= count++;front=Array+ start;last=front;lastA[ListNum]=last;frontA[ListNum]=front;}
template<class T>
void
MultipleTable<T>::insert(T value){if( (ListNum==count-1 && lastA[ListNum]< Array+MaxSize) || last[ListNum]<front[ListNum+1]){//如果还有空间 直接插到尾部 *++lastA[ListNum]=value;}else if(ListNum>0 && front[ListNum]>last[ListNum-1]){//查看前面有无空间Move_forward(ListNum); *++lastA[ListNum]=value;}else  {    // 前后都是满的int index = 1;bool flag = false;while(index <=ListNum)if(Move_forward(index++) ) //循环移0-i表flag = true;if(flag) //至少一移动了一个*++lastA[ListNum]=value;else{index=count-1;flag =false;while(index > ListNum)//i+1 到M 向后移 if(Move_backward(index--))flag =true;if(flag) *++lastA[ListNum]=value;else cout<<"fluat!!"<<endl,exit(1); //总空间已满}}
}
template<class T>
void
MultipleTable<T>::erase(int index){if(index<1 )cout<<"-1"<<endl,exit(1);copy(frontA[ListNum]+index+1,lastA[ListNum]+1,frontA[ListNum]+ index);lastA[ListNum]--;//指针向前移一格}
bool Move_forward(int ListNum){//移动到上一个尾部   0 第一个链表    count-1 最后一个链表    MaxSize 总数组容亮if(ListNum ==0||frontA[ListNum]==lastA[ListNum-1]+1)return false; int lenth=frontA[ListNum]-lastA[ListNum];copy(frontA[ListNum]+1,lastA[ListNum],lastA[ListNum-1]+2); //front指向 上一个表last的下一个 frontA[ListNum]=lastA[ListNum-1]+1;lastA[ListNum]=frontA[ListNum]+lenth;return true;}boolMove_backward(int ListNum){if( (ListNum!=::count-1 && lastA[ListNum]+1 == frontA[ListNum+1]) || lastA[ListNum]+1 == Array+MaxSize ) //紧挨着下一个  return false;int lenth=frontA[ListNum]-lastA[ListNum];if(ListNum==::count-1  ){//最后一个未满 copy_backward(frontA[ListNum]+1,lastA[ListNum]+1,Array+MaxSize);lastA[ListNum]= Array+MaxSize-1;frontA[ListNum]=lastA[ListNum]-lenth;}else { //一般情况 中间 copy_backward(frontA[ListNum]+1,lastA[ListNum]+1,frontA[ListNum+1]);lastA[ListNum]= frontA[ListNum+1]-1;frontA[ListNum]= lastA[ListNum]-lenth;}return true;}int main(){MultipleTable<Type> a(0),b(40);a.insert(666);cout<< *lastA[a.ListNum]<<endl;a.insert(888);a.erase(2);cout<< *lastA[a.ListNum]<<endl;return 0;
}

5.44

略  ,自行实现STL函数,大部分用指针

然后用第四章的方法测速

第五章总结 

抽象数据类型:

不依赖语言而描述,ADT  ,类提供接口

c++:  抽象类的派生类(抽象类的函数全部具体重写的派生类才算实体类,才能实例化)

本章主要讲解了 关于线性表 -- 数组描述

创建一个类包含对数组线性的许多方法 ,但会造成空间浪费 ;

一个数组实现多重表(省空间,但是操作复杂)

基于数组的类 vector ,也有许多方法,也支持迭代器

自写迭代器类:还不太懂 继续学习c++(重载 指针操作?)

第六章

chain总代码:(未完待续)

#include<iostream>
#include<string>
#include<sstream>
using namespace std;
class arrayList;
class illegaParameterValue{public:illegaParameterValue(): message("Illegal value"){}illegaParameterValue(char * theMessage){message = theMessage;}void outputMessage(){ cout<< message<<endl;}private:string message;
};
template<class T> // 抽象类 相当于提供接口?  派生类定义这些函数?
class linearList{// 都是纯虚函数public:virtual ~linearList(){};virtual bool empty() const =0;virtual int size()const =0;virtual T& get(int theIndex) const =0;virtual int indexOF(const T& theElement) const = 0;virtual void erase(int index) =0;virtual void insert(int theIndex,const T& theElment) = 0;virtual void output(ostream &out) const =0;
};
template<class T>
struct chainNode{//结构体也能构造 成员,函数T element;chainNode<T> *next;chainNode(){}chainNode(const T& element){ this->element= element;}chainNode(const T& element,chainNode<T> * next){this->element= element;this->next=next;}
};
template<class T>
class chain : public linearList<T>{//抽象类的派生类public:chain(int init =10);chain(const chain<T>&);~chain();bool empty() const {return listSize == 0;}//1int size() const {return listSize ;} //1T& get(int theIndex) const;//返回索引的元素 int indexOF(const T& theElment) const;//第一次出现的索引void erase(int theIndex);void insert(int theIndex,const T& theElement);void output(ostream & out) const;void swap(chain<T>& theChain);//交换两个链表//      /习题 void setSize(int theSize);//若多于 则删除  1void set(int theIndex,T theElement);//置换索引元素int lastIndexOf(T theElement);//元素最后出现索引void removeRange(int fromIndex,int toIndex);//删除索引范围内的所有节点T& operator[](int index);bool operator==(chain<T> & x);bool operator!=(chain<T>& x);bool operator<(chain<T>& x);void leftShift(int i);//左移动元素 (删除—)void reverse();//颠倒元素顺序 void meld(chain<T>& a,chain<T>& b);//交替合并void clean();//清空void merge(chain<T>& a,chain<T>& b);//有序合并 void split(chain<T>& a,chain<T>& b);//分奇偶索引void circularShift(int i);//向左循环索引void insertSort();//链表排序void binSort(int range);
///friend ostream& operator<<(ostream& out,const chain<T>& x){ x.output(out); return out;}protected:void checkIndex(int theIndex) const;chainNode<T>* firstNode;int listSize;
};
template<class T>
class extendedLinearList: linearList<T>{public:virtual ~extendedLinearList(){}virtual void clear()=0; //清楚表的所有元素virtual void push_back(const T& theElement) =0;//尾添法protected :chainNode<T> * lastNode;//指向最后一个节点  还要提供改进的代码 ~inseat等
};
template<class T>
void
chain<T>:: checkIndex(int theIndex) const{if( theIndex<0 || theIndex >= listSize)throw illegaParameterValue();
}
// 构造 template<class T>chain<T>:: chain(int init){if(init <1){ostringstream s; //该类能够根据内容自动分配内存,并且其对内存的管理也是相当的到位。 sprintfs<<"initial capacity must >0 ";throw illegaParameterValue();//为什么书上不行}firstNode = NULL;listSize =0; }template<class T>chain<T>::chain(const chain<T>& x){//赋值构造函数listSize =x.listSize ;if(listSize== 0){firstNode = NULL;return;}chainNode<T>* sourceNode = x.firstNode;firstNode= new chainNode<T> (sourceNode->element);sourceNode = sourceNode->next;chainNode<T>* targetNode =firstNode;while(sourceNode != NULL){targetNode->next = new chainNode<T>(sourceNode->element);targetNode = targetNode->next;sourceNode = sourceNode->next;}targetNode->next = NULL;}template<class T>
chain<T>::~chain(){while(firstNode != NULL){chainNode<T>* deleteNode = firstNode;firstNode=firstNode->next;delete deleteNode;}
}
template<class T>
T&
chain<T>::get(int index) const{checkIndex(index);chainNode<T>* currentNode= firstNode;for(int i =0;i<index;i++)currentNode=currentNode->next; //就是指向 第index个节点 return currentNode->element;
}
template<class T>
int
chain<T>::indexOF(const T& theElment) const{chainNode<T>* currentNode =firstNode;for(int i =0;i<listSize;i++){if(currentNode->element ==theElment)return i;currentNode= currentNode->next;}return -1;
}
template<class T>
void
chain<T>::erase(int theIndex){checkIndex(theIndex);chainNode<T>* deleteNode;if(theIndex == 0) {//是第一个节点deleteNode = firstNode;firstNode = firstNode->next;}else {chainNode<T>* preNode =firstNode;for(int i=0;i<theIndex -1;i++){ //指向索引的前驱preNode =preNode->next;}deleteNode = preNode->next;preNode->next = preNode->next->next ;}delete  deleteNode;listSize--;}
template<class T>
void
chain<T>::insert(int theIndex,const T& theElement){if(theIndex<0|| theIndex >listSize)throw illegaParameterValue();if(theIndex ==0)firstNode= new chainNode<T>(theElement,firstNode);else{chainNode<T>* currentNode= firstNode;for(int i=0;i<theIndex-1;i++)currentNode=currentNode->next;currentNode->next =new chainNode<T>(theElement,currentNode->next);  //37row    }listSize++;
}
template<class T>
void
chain<T>::output(ostream & out) const{for(chainNode<T>* currentNode =firstNode;currentNode!= NULL;currentNode=currentNode->next)out<<currentNode->element <<' ';out<<endl;}
template<class T>
void
chain<T>::setSize(int theSize){checkIndex(theSize);chainNode<T>* pre= firstNode;for( int i=0;i<theSize-1;i++)pre=pre->next;chainNode<T>* deleteNode;pre->next=NULL;chainNode<T>* currentNode =pre->next;while(currentNode!=NULL){deleteNode =currentNode;currentNode=currentNode->next;delete deleteNode;}listSize=theSize;
}
template<class T>
void
chain<T>::set(int theIndex,T theElement){checkIndex(theIndex);chainNode<T>*  current =firstNode;for(int i=0;i<theIndex;i++)current=current->next; current->element = theElement;
}
template<class T>
int
chain<T>::lastIndexOf(T theElement){int index=0;int i;chainNode<T>*  current =firstNode;for(i=0;i<listSize-1;i++){//索引 只有listsize-1  if(theElement == current->element)index =i;current= current->next;}if(i<listSize)return index;return -1;}
template<class T>
void
chain<T>::removeRange(int fromIndex,int toIndex){checkIndex(fromIndex);checkIndex(toIndex);chainNode<T> * currentNode =firstNode,*lift,*right;for(int i=0;i<toIndex;i++){currentNode= currentNode->next;}right = currentNode;//确定尾部 if( fromIndex == 0){lift=firstNode;firstNode = right->next;}else {currentNode =firstNode;for(int i = 0;i<fromIndex-1;i++)currentNode=currentNode->next;lift = currentNode->next;currentNode->next = right->next;}while(lift!=right){//删除currentNode = lift;lift =lift->next;delete currentNode;}delete lift;listSize -= toIndex-fromIndex+1;
}
template<class T>
T&
chain<T>::operator[](int index){return   get(index);
}
template<class T>
bool
chain<T>::operator==(chain<T> & x){if(listSize != x.listSize)return false;chainNode<T> *a=firstNode,*b = x.firstNode;for(int i=0;i<listSize;i++){if(a->element != b->element)return false;a=a->next;b=b->next;}return true;
}
template<class T>
bool
chain<T>:: operator!=(chain<T>& x){return ! (*this == x);
}
template<class T>
bool
chain<T>::operator<(chain<T>& x){chainNode<T> *a=firstNode,*b = x.firstNode;while(a!=NULL && b!=NULL){if(a->element<b->element)return true;else if(a->element>b->element)return false;a=a->next;b=b->next;}if( (a== NULL&& b==NULL) || b==NULL)return false; return true;}
template<class T>
void
chain<T>::swap(chain<T> &theChain){//改指向就行 chainNode<T> * temp = firstNode;firstNode = theChain.firstNode;theChain.firstNode = temp;
}
// template<class T>
// chain<T>&
// arrayToChain(arrayList<T> &array){
//         chain<T> temp(arrayList.size());//还是要自己插入
//         for(int i =0;i<arrayList.size();i++){
//                  temp.insert(i,array.get(1));
//       }
//         return temp;
// }
// template<class T>
// arrayList<T>&
// chainToArray(chain<T>& chain){
//        arrayList<T> temp(chain.size());
//          for(int i=0; i<chain.size();i++)
//               temp.insert(i,chain.get(i));//               return temp;
// }
template<class T>
void
reverse(chain<T>& x){x.reverse();
}
template<class T>
void
chain<T>::reverse(){chainNode<T> * pre=NULL,*current=firstNode,*next; //指针换方向??while(current !=NULL){next = current->next;current->next =pre;//反向pre=current;current=next;    }firstNode = pre;
}
template<class T>
void
chain<T>::leftShift(int i){//删除左边几个?for(int k=0;k<i;k++) erase(0); //只删除第一个
}template<class T>chain<T>&meld(chain<T> &a,chain<T> &b){chain<T> *temp= new chain<T> ;int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){temp->insert(k++,a.get(i++));temp->insert(k++,b.get(j++));}while(i<a.size()){temp->insert(k++,a.get(i++));}while(j<b.size()){temp->insert(k++,b.get(j++));}return *temp;}template<class T>voidchain<T>::meld(chain<T>& a,chain<T>& b){int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){insert(k++,a.get(i++));insert(k++,b.get(j++));}while(i<a.size()){insert(k++,a.get(i++));}while(j<b.size()){insert(k++,b.get(j++));}a.clean();b.clean();}template<class T>void chain<T>::clean(){chainNode<T>* deleteNode;while(firstNode != NULL){deleteNode =firstNode;firstNode=firstNode->next;delete deleteNode;}}template<class T>voidchain<T>::merge(chain<T>& a,chain<T>& b){int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){if(a.get(i)<=b.get(j))  insert(k++,a.get(i++));else  insert(k++,b.get(j++));}while(i<a.size()){insert(k++,a.get(i++));}while(j<b.size()){insert(k++,b.get(j++));}a.clean();b.clean();}template<class T>
voidsplit(chain<T>& a,chain<T>& b,chain<T>& c){int i=0,j=0,k=0;while(k<c.size()){if(k%2 ==0 )b.insert(j++,c.get(k++)); //b存偶数索引else a.insert(i++,c.get(k++));}}template<class T>void chain<T>::split(chain<T>&a,chain<T>&b){int i=0,j=0,k=0;while(k<size()){if(k%2 ==0 )b.insert(j++,get(k++)); //b存偶数索引else a.insert(i++,get(k++));}}
template<class T>
void
chain<T>::circularShift(int num){int i =0;while(i<num){insert(size(),get(0));erase(0);i++;}
}
template<class T>
void
chain<T>::insertSort(){int i ,j,key;for(i =0;i<size();i++){ key = get(i); // size ^2j=i-1;//sizewhile((j>=0) && (key<get(j))){//iset(j+1,get(j));  // i^2 *size  ==size^3    bed size^2j--;}set(j+1,key); // i^2}
}
template<class T>
void
chain<T>::binSort(int range){//range 就相当于基数chainNode<T> ** bottom= new chainNode<T>*[range+1];//桶底,头指针 指向节点 chainNode<T> ** top =   new chainNode<T>*[range+1];//顶 尾指针for(int i=0;i<=range;i++)bottom[i]= NULL ;   //初始所有桶为空while(firstNode!=NULL){int theBin = firstNode->element; //取数据 分到类桶中989 if(bottom[theBin] == NULL)bottom[theBin]= top[theBin] = firstNode;else{top[theBin]->next =firstNode;top[theBin]=firstNode; //尾巴移动}firstNode= firstNode->next;}chainNode<T>* last =NULL ;for(int theBin=0;theBin<=range;theBin++){if(bottom[theBin] != NULL){if(last ==NULL)//一个桶没合并firstNode =bottom[theBin];else last->next = bottom[theBin];last= top[theBin]; //移到当前桶尾部}if(last !=NULL )last->next =NULL;} //利用原来链表空间delete [] bottom;delete [] top;}int main(){chain<int> a,b,c;try{for(int i=0;i<10;i++)a.insert(i,9-i);//桶有范围的for(int i=0;i<10;i++)a.insert(i,9-i);cout<<a<<endl;a.binSort(10);cout<<a<<endl;}catch(illegaParameterValue e) {e.outputMessage();return 1;}return 0;}

6.1

最终结果: {agbdeh}

6.2

O(listSize-theSize)

template<class T>
void
chain<T>::setSize(int theSize){checkIndex(theSize);chainNode<T>* pre= firstNode;for( int i=0;i<theSize-1;i++)pre=pre->next;chainNode<T>* deleteNode;pre->next=NULL;chainNode<T>* currentNode =pre->next;while(currentNode!=NULL){deleteNode =currentNode;currentNode=currentNode->next;delete deleteNode;}listSize=theSize;
}

6.3

O(theindex)

chain<T>::set(int theIndex,T theElement){checkIndex(theIndex);chainNode<T>*  current =firstNode;for(int i=0;i<theIndex;i++)current=current->next; current->element = theElement;
}    

6.4

O(toIndex)

template<class T>
void
chain<T>::removeRange(int fromIndex,int toIndex){checkIndex(fromIndex);checkIndex(toIndex);chainNode<T> * currentNode =firstNode,*lift,*right;for(int i=0;i<toIndex;i++){currentNode= currentNode->next;}right = currentNode;//确定尾部 if( fromIndex == 0){lift=firstNode;firstNode = right->next;}else {currentNode =firstNode;for(int i = 0;i<fromIndex-1;i++)currentNode=currentNode->next;lift = currentNode->next;currentNode->next = right->next;}while(lift!=right){//删除currentNode = lift;lift =lift->next;delete currentNode;}delete lift;listSize -= toIndex-fromIndex+1;
}

6.5

O(listSize)

template<class T>
int
chain<T>::lastIndexOf(T theElement){int index=0;int i;chainNode<T>*  current =firstNode;for(i=0;i<listSize-1;i++){//索引 只有listsize-1  if(theElement == current->element)index =i;current= current->next;}if(i<listSize)return index;return -1;}

6.6

template<class T>
T&
chain<T>::operator[](int index){return   get(index);
}

6.7

template<class T>
bool
chain<T>::operator==(chain<T> & x){if(listSize != x.listSize)return false;chainNode<T> *a=firstNode,*b = x.firstNode;for(int i=0;i<listSize;i++){if(a->element != b->element)return false;a=a->next;b=b->next;}return true;
}

6.8

template<class T>
bool
chain<T>:: operator!=(chain<T>& x){return ! (*this == x);
}

6.9

template<class T>
bool
chain<T>::operator<(chain<T>& x){chainNode<T> *a=firstNode,*b = x.firstNode;while(a!=NULL && b!=NULL){if(a->element<b->element)return true;else if(a->element>b->element)return false;a=a->next;b=b->next;}if( (a== NULL&& b==NULL) || b==NULL)return false; return true;}

6.10

O(1)

template<class T>
void
chain<T>::swap(chain<T> &theChain){//改指向就行 chainNode<T> * temp = firstNode;firstNode = theChain.firstNode;theChain.firstNode = temp;
}

6.11-6.12

template<class T>
chain<T>&
arrayToChain(arrayList<T> &array){chain<T> temp(arrayList.size());//还是要自己插入 for(int i =0;i<arrayList.size();i++){temp.insert(i,array.get(1));}return temp;
}
template<class T>
arrayList<T>&
chainToArray(chain<T>& chain){arrayList<T> temp(chain.size());for(int i=0; i<chain.size();i++)temp.insert(i,chain.get(i));return temp;
}

不会迭代器类型

6.13

一样的 只不过变为成员函数。

复杂度都是O(listSize^2)

6.14

O(i)  一直为最好情况删除

template<class T>
void
chain<T>::leftShift(int i){//删除左边几个?for(int k=0;k<i;k++) erase(0); //只删除第一个
}

6.15-6.16

O(listSize)    设置三个指针 转向链表,而不是像数组一样互换值

template<class T>
void
reverse(chain<T>& x){x.reverse();
}
template<class T>
void
chain<T>::reverse(){chainNode<T> * pre=NULL,*current=firstNode,*next; //指针换方向??while(current !=NULL){next = current->next;current->next =pre;//反向pre=current;current=next;    }firstNode = pre;
}

6.17-6.18

O(a.size+b.size)

template<class T>//非成员函数chain<T>&meld(chain<T> &a,chain<T> &b){chain<T> *temp= new chain<T> ;int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){temp->insert(k++,a.get(i++));temp->insert(k++,b.get(j++));}while(i<a.size()){temp->insert(k++,a.get(i++));}while(j<b.size()){temp->insert(k++,b.get(j++));}return *temp;}
template<class T>chain<T>&meld(chain<T> &a,chain<T> &b){chain<T> *temp= new chain<T> ;int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){temp->insert(k++,a.get(i++));temp->insert(k++,b.get(j++));}while(i<a.size()){temp->insert(k++,a.get(i++));}while(j<b.size()){temp->insert(k++,b.get(j++));}return *temp;}template<class T>voidchain<T>::meld(chain<T>& a,chain<T>& b){int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){insert(k++,a.get(i++));insert(k++,b.get(j++));}while(i<a.size()){insert(k++,a.get(i++));}while(j<b.size()){insert(k++,b.get(j++));}a.clean();b.clean();}
template<class T>void chain<T>::clean(){chainNode<T>* deleteNode;while(firstNode != NULL){deleteNode =firstNode;firstNode=firstNode->next;delete deleteNode;}}

6.19-6.20

O(a.size+b.size)

template<class T>voidchain<T>::merge(chain<T>& a,chain<T>& b){int i=0,j=0,k=0;while(i<a.size()&&j<b.size()){if(a.get(i)<=b.get(j))  insert(k++,a.get(i++));else  insert(k++,b.get(j++));}while(i<a.size()){insert(k++,a.get(i++));}while(j<b.size()){insert(k++,b.get(j++));}a.clean();b.clean();}

6.21-22

O(size)

template<class T>
voidsplit(chain<T>& a,chain<T>& b,chain<T>& c){int i=0,j=0,k=0;while(k<c.size()){if(k%2 ==0 )b.insert(j++,c.get(k++)); //b存偶数索引else a.insert(i++,c.get(k++));}}template<class T>void chain<T>::split(chain<T>&a,chain<T>&b){int i=0,j=0,k=0;while(k<size()){if(k%2 ==0 )b.insert(j++,get(k++)); //b存偶数索引else a.insert(i++,get(k++));}}

6.23

O(num *size)

template<class T>
void
chain<T>::circularShift(int num){int i =0;while(i<num){insert(size(),get(0));erase(0);i++;}
}

6.24-25

双向循环链表 ? 没明白什么意思 "当移动到p时“ 是指p尾结点的时候?

思路:  设置两个指针呗 一个指向前驱 一个 后继

6.26

最坏 O(size^3)

最好O(sisze^2)

template<class T>
void
chain<T>::insertSort(){int i ,j,key;for(i =0;i<size();i++){ key = get(i); // size ^2j=i-1;//sizewhile((j>=0) && (key<get(j))){//iset(j+1,get(j));  // i^2 *size  ==size^3    bad size^2j--;}set(j+1,key); // i^2}
}

6.27

略 ,思路跟排序一样 只不过数组换成了链表  元素还是一样交换

时间复杂度应该都加了一个最高次   因为数组取元素为O(1)  而链表为O(n)

6.28 - 6.42 (带头结点的循环指针)

#include<iostream>
using namespace std;
template<class T>
struct chainNode{//结构体也能构造 成员,函数T element;chainNode<T> *next;chainNode(){}chainNode(const T& element){ this->element= element;}chainNode(const T& element,chainNode<T> * next){this->element= element;this->next=next;}
};
template<class T>
class circularList{public: circularList();~circularList();void insert(T element);void eraseNode(chainNode<T>* x);chainNode<T>*  rePoin(int index);//返回索引节点的指针friend ostream& operator<<(ostream& out,const circularList<T>& x){ x.output(out); return out;}void output(ostream & out) const;private:chainNode<T> *headerNode;   int listSize;
};
template<class T>
circularList<T>::circularList(){headerNode = new chainNode<T>();headerNode->next = headerNode;listSize =0;
}
template<class T>
void
circularList<T>::output(ostream & out) const{chainNode<T>* current;for(current =headerNode->next;current!=headerNode;current=current->next)out<<current->element<<' ';out<<endl;}
template<class T>
circularList<T>::~circularList(){while(headerNode->next != headerNode){chainNode<T>* dele = headerNode->next;headerNode ->next = dele->next;delete dele;}
}
template<class T>
void
circularList<T>::insert(T value){//插入尾部chainNode<T>* pre=headerNode;while(pre->next != headerNode)pre=pre->next;pre->next = new chainNode<T>(value,headerNode);listSize++;}
template<class T>
void
circularList<T>::eraseNode(chainNode<T>* x){//只知道指向的指针   最好 O(1)  最坏 O(n) if(x->next == headerNode){ //是最后一个节点  必须要遍历??chainNode<T>* pre = headerNode->next;while(pre->next!=x)pre=pre->next;  pre->next = headerNode;delete x;}        else {x->element =x->next->element; //覆盖数据 删除下一节点 chainNode<T>* dele = x->next;x->next =x->next->next;delete dele;}  }
template<class T>
chainNode<T>*
circularList<T>:: rePoin(int index){//返回索引节点的指针chainNode<T>* temp = headerNode->next;for(int i =0;i<index;i++)temp=temp->next;return temp;}int main(){circularList<int>  a;a.insert(5);a.insert(888);a.insert(666);a.insert(88888);a.eraseNode(a.rePoin(1));a.eraseNode(a.rePoin(0));cout<<a<<endl;return 0;
}

重复的没做 思路是一样的 只是循环了

6.43 -6.61(双向循环链表等

#include<iostream>
using namespace std;
template<class T>
struct Node{T element;Node<T> *pre;Node<T> *next;Node(){}Node(const T& value){this->element = value;}Node(const T& value,Node<T> *pre, Node<T> *next){this->element =value;this->next = next;this->pre = pre;}};
template<class T>
class doubleCircularList{//带头结点的双向链表public:doubleCircularList();~doubleCircularList();void insert(T element);friend ostream& operator<<(ostream& out,const doubleCircularList<T>& x){ x.output(out); return out;}
void output(ostream & out) const;
void merge(doubleCircularList<T>& x);//合并到表尾 ;
T get(int idnex);//如果小于size/2 左查找 private: Node<T>* headerNode;int listSize;
};
template<class T>
doubleCircularList<T>::doubleCircularList(){headerNode = new Node<T>();headerNode->next=headerNode->pre=headerNode;listSize++;
}
template<class T>
void
doubleCircularList<T>::output(ostream & out) const{Node<T>* current;for(current =headerNode->next;current!=headerNode;current=current->next)out<<current->element<<' ';out<<endl;
}
template<class T>
doubleCircularList<T>::~doubleCircularList(){while(headerNode->next != headerNode){Node<T>* dele = headerNode->next;headerNode ->next = dele->next;delete dele;}
}
template<class T>
void
doubleCircularList<T>:: insert(T element){Node<T>* pre =headerNode->next;while(pre->next !=  headerNode)pre=pre->next;pre->next = new Node<T>(element,pre,headerNode);headerNode->pre = pre->next;listSize++;}
template<class T>
void
doubleCircularList<T>:: merge(doubleCircularList<T>& x){x.headerNode->next->pre = headerNode->pre;//b表前驱改为 a表尾部headerNode->pre->next=x.headerNode->next;//a表尾部后驱 改为a表第一个x.headerNode->pre->next = headerNode;//b 表最后改为 a表头x.headerNode->next=x.headerNode;x.headerNode->pre =x.headerNode;}
template<class T>
T
doubleCircularList<T>:: get(int index){Node<T>* current;if (index<listSize/2){current= headerNode->next;for(int i=0;i<index;i++)current=current->next;}else {current=headerNode->pre;for(int i =listSize-1;i>index;i--)current=current->pre;}return current->element;
}
int main(){
doubleCircularList<int> a,b;
a.insert(1);
a.insert(888);
a.insert(55);
b.insert(345);cout<<a.get(2)<<endl<<b.get(0)<<endl;return 0;
}

方便很多 因为可以直接定位到最后一个节点O(1)

6.62

是稳定的 在链表前部的先入桶 合并也是先入链

6.63

自行测试

6.64(基数排序)

emplate<class T>
void
chain<T>::binSort(int range,int d){//range 就相当于基数chainNode<T> ** bottom= new chainNode<T>*[range+1];//桶底,头指针 指向节点 chainNode<T> ** top =   new chainNode<T>*[range+1];//顶 尾指针for(int i=0;i<=range;i++)bottom[i]= NULL ;   //初始所有桶为空int div = pow(range,d); int mod= pow(range,d+1);while(firstNode!=NULL){int theBin = (firstNode->element%mod) /div; //取数据 分到类桶中989 **重点在这基数排序if(bottom[theBin] == NULL)bottom[theBin]= top[theBin] = firstNode;else{top[theBin]->next =firstNode;top[theBin]=firstNode; //尾巴移动}firstNode= firstNode->next;}chainNode<T>* last =NULL ;for(int theBin=0;theBin<=range;theBin++){if(bottom[theBin] != NULL){if(last ==NULL)//一个桶没合并firstNode =bottom[theBin];else last->next = bottom[theBin];last= top[theBin]; //移到当前桶尾部}if(last !=NULL )last->next =NULL;} //利用原来链表空间delete [] bottom;delete [] top;}
template<class T>
void
chain<T>::radixSort(int range,int d){//基数r 按基数r分解的个数dfor(int i=0;i < d;i++){binSort(range,i);}
}

调用d次binSort 每次 2range(初始化+合并)+放桶listSize

一共  O(d(r+n)) 复杂度

6.51

一样的。

0-n^c-1 可以拆解成 n*n*n.....一共c个n相乘

每次比较一个基数n就行了

6.66

一样的三次桶排序。 先比优先级最小的

6.67-68

共线怎么计算最长两点?遍历Cn2?

极角不会

入栈 三个点为一组(第二个点大于180 则出栈不是极点

凸包算法详解(convex hull)_viafcccy的博客-CSDN博客_convex hull

(1条消息) 叉积(向量之间的计算)_Puppet__的博客-CSDN博客_叉积运算

#include<iostream>
#include<stdlib.h>
using namespace std;
template<class T>
struct Node{T x;T y;Node<T> *pre;Node<T> *next;Node(){}Node(const T& x,const T& y){this->x = x;this->y =y;}Node(const T& x,const T& y,Node<T> *pre, Node<T> *next){this->x = x;this->y =y;this->next = next;this->pre = pre;}};
template<class T>
class doubleCircularList{//带头结点的双向链表public:doubleCircularList();~doubleCircularList();void insert(const T& x,const T& y);friend ostream& operator<<(ostream& out,const doubleCircularList<T>& x){ x.output(out); return out;}
void output(ostream & out) const;
void merge(doubleCircularList<T>& x);//合并到表尾 ;
T get(int idnex);//如果小于size/2 左查找
bool
checkCollinear();
void
angle(); //按极角排序 private:Node<T>* headerNode;int listSize;
};
template<class T>
doubleCircularList<T>::doubleCircularList(){headerNode = new Node<T>();headerNode->next=headerNode->pre=headerNode;listSize=0;
}
template<class T>
void
doubleCircularList<T>::output(ostream & out) const{Node<T>* current;for(current =headerNode->next;current!=headerNode;current=current->next)out<<current->x<<' '<<current->y<<endl;}
template<class T>
doubleCircularList<T>::~doubleCircularList(){while(headerNode->next != headerNode){Node<T>* dele = headerNode->next;headerNode ->next = dele->next;delete dele;}
}
template<class T>
void
doubleCircularList<T>:: insert(const T& x,const T& y){Node<T>* pre =headerNode->next;while(pre->next !=  headerNode)pre=pre->next;pre->next = new Node<T>(x,y,pre,headerNode);headerNode->pre = pre->next;listSize++;}
template<class T>
void
doubleCircularList<T>:: merge(doubleCircularList<T>& x){x.headerNode->next->pre = headerNode->pre;//b表前驱改为 a表尾部headerNode->pre->next=x.headerNode->next;//a表尾部后驱 改为a表第一个x.headerNode->pre->next = headerNode;//b 表最后改为 a表头x.headerNode->next=x.headerNode;x.headerNode->pre =x.headerNode;}
template<class T>
T
doubleCircularList<T>:: get(int index){Node<T>* current;if (index<listSize/2){current= headerNode->next;for(int i=0;i<index;i++)current=current->next;}else {current=headerNode->pre;for(int i =listSize-1;i>index;i--)current=current->pre;}return current->element;
}
struct coordinate{coordinate(){};coordinate(double x,double y);double x;double y;
};
coordinate::coordinate(double x,double y){this->x = x;this->y = y;
}
template<class T>
Node<T>&
interior_point(Node<T> &a,Node<T>& b,Node<T>& c){time_t t;srand((unsigned)time(&t));double x1 = (double)(rand()%100)/100;double x2=(double)(rand()%100)/100;if(x1+x2 > 1){x1=1-x1;x2=1-x2;}double x= a.x+x1*(b.x-a.x)+x2*(c.x-a.x);double y= a.y+x1*(b.y-a.y)+x2*(c.y-a.y);Node<T> * temp = new Node<T>(x,y);return *temp;
}
template<class T>
bool
doubleCircularList<T>::checkCollinear(){if(listSize<3){cout<<"error"<<endl;return false;}Node<T>* current = headerNode->next;double x1=current->x,y1=current->y;current=current->next;double x2=current->x,y2=current->y;// double max=pow((x2-x1),2)+(pow(y2-y1),2);// x-x1 * x2-x1  -  y-y1 *y2-y1 ==0  共线bool flag = 1;for(current=current->next;current->next !=  headerNode;current=current->next){if( (current->x-x1)*(x2-x1)-(current->y-y1)*(y2-y1) !=0){flag = 0;break;}}if(flag == 0){Node<T> temp =interior_point(*headerNode->next,*headerNode->next->next,*current);cout<<temp.x<<' '<<temp.y<<endl;return false;}return true;}
int main(){doubleCircularList<double> a;a.insert(2,5);a.insert(2,5);a.insert(2,5);cout<< a.checkCollinear()<<endl;return 0;
}

6.69

(1条消息) 高精度运算——加减乘除(超详细模板)_Sqi的博客-CSDN博客

链表太麻烦了

6.70-71

只实现了加法

#include<iostream>
using namespace std;
template<class T>
struct chainNode{//结构体也能构造 成员,函数T element;chainNode<T> *next;chainNode(){}chainNode(const T& element){ this->element= element;}chainNode(const T& element,chainNode<T> * next){this->element= element;this->next=next;}
};
struct polynomial{int exp;//指数int coeff;//系数polynomial* next;polynomial(){exp =0;  coeff =-1; next=NULL;}polynomial(int exp,int coeff){this->exp=exp;this->coeff = coeff;}};template<class T>
class circularList{public:circularList();~circularList();void insert(T ,T);int degree();//返回最高次void  intput();circularList<T>& add(circularList<T>& b);friend ostream& operator<<(ostream& out,const circularList<T>& x){ x.output(out); return out;}void output(ostream & out) const;private:struct polynomial *headerNode;int listSize;
};
template<class T>
circularList<T>::circularList(){headerNode = new polynomial();headerNode->next = headerNode;listSize =0;
}
template<class T>
void
circularList<T>::output(ostream & out) const{polynomial* current;for(current =headerNode->next;current!=headerNode;current=current->next){cout<<current->coeff <<"x^"<<current->exp<<'+';}cout<<0;out<<endl;}
template<class T>
circularList<T>::~circularList(){while(headerNode->next != headerNode){polynomial* dele = headerNode->next;headerNode ->next = dele->next;delete dele;}
}
template<class T>
void
circularList<T>::insert(T exp,T coeff){//插入尾部polynomial* pre=headerNode;while(pre->next != headerNode)pre=pre->next;pre->next = new polynomial(exp,coeff);pre->next->next=headerNode;}
template<class T>
int
circularList<T>::degree(){return headerNode->next->exp;
}
template<class T>
void
circularList<T>::intput(){cout<<"请输入个数?"<<endl;cin>>listSize;cout<<"请输入序列"<<endl;int exp,cofeff;for(int i=0;i<listSize;i++){cin>>exp>>cofeff;insert(exp,cofeff);}
}
template<class T>
circularList<T>&
circularList<T>::add(circularList<T>& b){polynomial *current = b.headerNode->next;polynomial* x=headerNode->next;if(current->exp>x->exp){//插入首polynomial* temp = new polynomial(current->exp,current->coeff);headerNode->next= temp;temp->next = x;current=current->next;}while(current!=b.headerNode){for(;x!=headerNode&&x->exp >=current->exp;x=x->next){if(current->exp == x->exp){x->coeff+= current->coeff;break;}if(x->next->exp<current->exp){polynomial* temp = new polynomial(current->exp,current->coeff);temp->next= x->next;x->next = temp;listSize++;break;}}current=current->next;}return *this;
}
int main(){circularList<int>  a,b;a.intput();b.intput();cout<<a<<endl<<b<<endl;a.add(b);cout<<a;return 0;
}

6.72

1) u次合并 每次都是原类+新类(一个)  所以总<= u+1

2)u次合并 都是 新类加新类(1+1)  所以单元素类至少为 n-2U

3) u-1 次合并后 就是包含所有单类了 不能再合并

6.73

#include<iostream>
using namespace std;
struct equivNode{int equivClass;int size;equivNode* next;
};
equivNode *node;
int n;
void init(int init_num){n= init_num;node = new equivNode[init_num+1];for(int e= 1;e<=n;e++){node[e].equivClass=e;node[e].next =NULL;node[e].size =1;}
}
int
Find(int classNum){return node[classNum].equivClass;//祖类  首节点就是当前大类的 }
void
unite(int a,int b){if( Find(a) != Find(b)){if(node[a].size > node[b].size){swap(a,b);//改变较小类的}equivNode* k=node+a;while(k->next!=NULL){k->equivClass=b;k=k->next;}k->equivClass=b;//小类a  插入到b首元素之后node[b].size+=node[a].size;k->next =  node[b].next;node[b].next= node+a;}
}
void show(){for(int i=1;i<=5;i++){cout<<i<<' '<<node[i].equivClass<<endl;}
}int main(){init(5);unite(1,2);unite(2,4);show();}

6.74

因为都是截止时间往前推 ,先定优先级高的(必须在某时间段完成) 再排优先级低的

6.75

后者性能高

6.76:

//数组查并集
#include<iostream>
using namespace std;
int *node;//整型数组
void init(int initNum){node = new int[initNum+1];for(int i =0;i<=initNum;i++) node[i]=i;
}
int
find(int classNum){if(node[classNum]== classNum)return classNum;else return find(node[classNum]);//找到祖类
}
void
unite(int classA,int classB){if(  find(node[classA] ) != find( node[classB] )  ){//不属于同一类node[classA]=classB; //默认归到B类 }
}
void show(){for(int i=1;i<=5;i++){cout<<i<<' '<<find(i)<<endl;}
}
int main(){init(10);unite(1,2);unite(2,4);show();return 0;}

查找 O(initNum)

合并 O(1)

初始化(initNUM)

一共(init )

6.77

见6.73

6.78

没看懂,服了!

第六章总结

线性表的链式描述:

单链表 /双链表

有无循环

有无头节点

排序:

桶排序:

基数排序(多次桶排序)

应用:

等价类

查并集

多项式

凸包(极角)

感觉应用很难 些脯肉

第七章

7.1:

i1*12+i2*4+i3*2+i4

7.2

一样的,* 剩下的维数

7.3

map(i1,i2,..,ik)= i1*u(k-1)+i2*u(k-2)+...+ik

U是剩下总维数

7.4

map(i1,i2,i3) =  i3*u2+i2*u1+i1

7.5

一样的,是后面的*列维数

7.6

map(i1,i2,..,in)=    ik*u(k-1)+i(k-1)*u(k-2)+...+i1

7.7

map(i1,i2)= (u1-i1-1)*u2+u2-i2

7.8

map(i1,i2)= u1*(u2-i2-1) +i1

7.9

实测  都是  sizeof(TYPE)*m*n

new 申请的二维数组才多出来一个指针对象

7.10

如果是new申请的  多 (n-1)维数*行数 个指针

维数很多时,一维数组快,可以直接计算一次地址就可以得到元素

7.11

同上

7.12

1)

(  u1+u2+...u(k-1)  ) *sizeof(*)+ u1u2u3..uk *sizeof(type)

// 每一个当前数组都储存指向内元素的指针,==里面元素的个数

直接一维数组的话 :

u1u2u3..uk *sizeof(type)

2)

比列:    假如指针和整型空间一样

1+          u1+u2+..u(k-1) / u1u2..uk

3)

访问指针次数过多时  ,而主映射下的一维数组实际只要计算一次

注意: 书上是错了吗? c和c++ 应该都一样  数组形式空间应该都是一样

都是通过步长来计算地址 ,只是类型不同,计算的地址也不同

7.13-14

关于对角线对称

7.15-7.16

#include<iostream>
#include<sstream>
using namespace std;
class illegaParameterValue{public:illegaParameterValue(): message("Illegal value"){}illegaParameterValue(char * theMessage){message = theMessage;}void outputMessage(){ cout<< message<<endl;}private:string message;
};
template<class T>
class matrix{friend istream& operator>>(istream& in,const matrix<T>& x){x.show(in); return in;}friend ostream& operator<<(ostream& out,const matrix<T>& x){ x.output(out); return out;}//在里面实例话 调用函数public:matrix(int theRows =0,int theColumns =0);matrix(const matrix<T>&);~matrix(){delete [] element ;}int rows(){return theRows;};int Columns(){return theColumns;}void output(ostream& )const;void show(istream& )const;matrix<T> & tranpose();//转置矩阵private:int theRows;int theColumns;T *element;
};template<class T>
matrix<T>::matrix(int row,int col){if((row<0||col<0)|| (row==0 &&col!=0)||(col==0&&row!=0))throw illegaParameterValue();element = new T [(row)*(col)];//映射为一维数组 且1开始表达theRows =row;theColumns = col;
}
template<class T>
void
matrix<T>::output(ostream & out)const{for(int i =0;i<theColumns*theRows;i++){if(i%theRows == 0)out<<endl;out<<element[i]<<' ';}cout<<endl;
}
template<class T>
void
matrix<T>::show(istream & in)const {for(int i =0;i<theColumns*theRows;i++)in>>element[i];}
template<class T>
matrix<T>&
matrix<T>::tranpose()
{    int i=0,j=0;for(;i<theRows;i++)for(;j<theColumns;j++)if(j>i)swap(element[theRows*i+j],element[theColumns*j+i]);swap(theColumns,theRows);return *this;
}
int main(){matrix<int> a(2,2);cin>>a;a.tranpose();cout<<a;return 0;
}

7.17

二维的表达方法好像前面写过  略

感觉其实性能差不多(物理逻辑上都是一纬线性的)

只是表达方式不一样,可能映射成一维数组,只要计算一次下标(地址),会快一点

但个人认为二维的表达更清楚

7.18

脑补画图

1)  下三角

2)  上三角

3)  上三角

7.19

1) 2,4 狗窝

2)     自己画

3)  三对角矩阵

7.20

一样的咯

无需转置矩阵

复杂度都是 O(n)   n为阶数

7.21

复杂度 O(n)

7.22

主要是找映射公示  蛮难找的 下标都是从 0开始

#include<iostream>
#include<sstream>
using namespace std;
class illegaParameterValue{public:illegaParameterValue(): message("Illegal value"){}illegaParameterValue(char * theMessage){message = theMessage;}void outputMessage(){ cout<< message<<endl;}private:string message;
};
template<class T>
class matrix{friend istream& operator>>(istream& in,const matrix<T>& x){x.input(in); return in;}friend ostream& operator<<(ostream& out,const matrix<T>& x){ x.output(out); return out;}//在里面实例话 调用函数public:matrix(int n=0);matrix(const matrix<T>&);~matrix(){delete [] element ;}void output(ostream& )const;void input(istream& )const;matrix<T> & tranpose();//转置矩阵private:int n;T *element;
};template<class T>
matrix<T>::matrix(int n){if(n<0)throw illegaParameterValue();element = new T [3*n-2];//映射为一维数组 且1开始表达this->n = n;
}
template<class T>
void
matrix<T>::output(ostream & out)const{int row,col;for(row =0;row<n;row++){for(col =0;col<n;col++){int temp = row-col;if(temp!= -1 && temp !=0 &&temp != 1)cout<< 0<< ' ';else           cout<<element[col*2+row]<<' ';      }cout<<endl;}cout<<endl;
}
template<class T>
void
matrix<T>::input(istream & in)const {for(int i =0;i<n*3-2;i++)//3n-2in>>element[i];}
int main(){matrix<int> a(4);cin>>a;cout<<a;return 0;
}

7.23

公示改一下

  cout<<element[row*2+col]<<' ';     

7.24

不是  每行每列都有数字

7.25

感觉不规则二维数组没什么意义

空间都是一样的

一维数组方便寻址

二维的可能更方便阅读和找映射方式

7.26

#include<iostream>
using  namespace std;
template<class T>
class lowerTriangleAsIrregularArray{public:lowerTriangleAsIrregularArray(int n=0);~lowerTriangleAsIrregularArray();friend istream& operator>>(istream& in,const lowerTriangleAsIrregularArray<T>& x){x.input(in); return in;}friend ostream& operator<<(ostream& out,const lowerTriangleAsIrregularArray<T>& x){ x.output(out); return out;}//在里面实例话 调用函数void output(ostream& )const;void input(istream& )const;private:int n;T** element;
};
template<class T>
lowerTriangleAsIrregularArray<T>::lowerTriangleAsIrregularArray(int n){this->n=n;element = new  T*[n];for(int i=1;i<=n;i++)element[i-1]=new T[i];}
template<class T>
lowerTriangleAsIrregularArray<T>::~lowerTriangleAsIrregularArray(){for(int i=0;i<n;i++)delete element[i];delete [] element;
}template<class T>
void
lowerTriangleAsIrregularArray<T>::input(istream & in) const{for(int i=0;i<n;i++){for(int j=0;j<i+1;j++)cin>>element[i][j];}
}
template<class T>
void
lowerTriangleAsIrregularArray<T>::output(ostream& out) const{for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(j<i+1)cout<<element[i][j]<<' ';else cout<<0<<' ';cout<<endl;}
}
int main(){
lowerTriangleAsIrregularArray<int> a(5);cin>>a;cout<<a;return 0;
}

7.27

一样的咯

把指针数组指向的一维数组倒叙就行

7.28-7.29

#include<iostream>
using  namespace std;
template<class T>
class lowerTrianglerArray{public:lowerTrianglerArray(int n=0);~lowerTrianglerArray();friend istream& operator>>(istream& in,const lowerTrianglerArray<T>& x){x.input(in); return in;}friend ostream& operator<<(ostream& out,const lowerTrianglerArray<T>& x){ x.output(out); return out;}//在里面实例话 调用函数void output(ostream& )const;void input(istream& )const;T* tranpose();//转置成上三角映射的一维数组 private:int n;T* element;
};
template<class T>
lowerTrianglerArray<T>::lowerTrianglerArray(int n){this->n=n;element = new  T[ (n+1)*n/2];}
template<class T>
lowerTrianglerArray<T>::~lowerTrianglerArray(){delete [] element;
}template<class T>
void
lowerTrianglerArray<T>::input(istream & in) const{//O(n^2)for(int i=0;i< (n+1)*n/2;i++)in>>element[i];
}
template<class T>
void
lowerTrianglerArray<T>::output(ostream& out) const{//O(n^2)for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(j<i+1)cout<<element[(i+1)*i/2 +j]<<' ';else cout<<0<<' ';cout<<endl;}
}
template<class T>
T*
lowerTrianglerArray<T>::tranpose(){//O(n)for(int start=0,end=(n+1)*n/2-1;start<end;start++,end--){swap(element[start],element[end]);}return element;
}
int main(){
lowerTrianglerArray<int> a(4);cin>>a;a.tranpose();cout<<a;return 0;
}

7.30

把其中一个主下三角转置成主上三角

这样就拼接成了一个方阵

把两个类的方法拼接一下就行了

7.31

下 *下 还是下三角矩阵

T**
lowerTrianglerArray<T>::multiplication(lowerTrianglerArray<T>& x){T ** result = new T*[n];for(int i=0; i<n;i++)result[i]= new T[n];//初始化int i, j, k, sum ;  for (i = 0; i < n; i++)           {for (j = 0; j <n; j++)   {  //分三种情况sum = 0;if(j>i) {result[i][j]= 0;}                                                                                                                                                  else if( i== j){result[i][j]=  element[(i+1)*i/2+j] * x.  element[(i+1)*i/2+j];}else {for(int k=j;k<n;k++)//对角线下边的  n-j 次 互* 其他为0 sum += element[(i+1)*i/2+k]*x.element[(k+1)*k/2+j]; result[i][j] = sum;}}}return result;}

O(n^3)   少了一些情况罢了

7.32

没有特殊性了

分两种情况{

i>= j  按行次数

i<j     按列次数

}

for(k=0;k<i(或者j);k++){
.....累加
}

7.33

总元素是 n*n/2

(i,j) == (j,i)  应该很简单

7.34

1) 按行压缩

2) n*n方阵 看成三排 重复两个   --> 3n-2

3)

#include<iostream>
using  namespace std;
template<class T>
class cMatrix{public:cMatrix(int n=0);~cMatrix();friend istream& operator>>(istream& in,const cMatrix<T>& x){x.input(in); return in;}friend ostream& operator<<(ostream& out,const cMatrix<T>& x){ x.output(out); return out;}//在里面实例话 调用函数void output(ostream& )const;void input(istream& )const;private:int n;T* element;
};
template<class T>
cMatrix<T>::cMatrix(int n){this->n=n;element = new  T[3*n-2];//c}
template<class T>
cMatrix<T>::~cMatrix(){delete [] element;
}template<class T>
void
cMatrix<T>::input(istream & in) const{//O(n^2)for(int i=0;i<3*n-2 ;i++)in>>element[i];
}
template<class T>
void
cMatrix<T>::output(ostream& out) const{//O(n^2)for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(i==0)cout<<element[j]<<' ';else if(i==n-1)cout<<element[2*n-2+j]<<' ';else if(j== 0)cout<<element[n+i-1]<<' ';else cout<<0<<' ';cout<<endl;}
}
int main(){
cMatrix<int> a(4);cin>>a;cout<<endl<<a;return 0;
}

7.35

2)

当且仅当 i+j == n+1 时 元素才能不为0

其实就是副对角线,有n个元素

3) 按行存呗

4)

#include<iostream>
using  namespace std;
template<class T>
class antidiagonalMatrix{public:antidiagonalMatrix(int n=0);~antidiagonalMatrix();friend istream& operator>>(istream& in,const antidiagonalMatrix<T>& x){x.input(in); return in;}friend ostream& operator<<(ostream& out,const antidiagonalMatrix<T>& x){ x.output(out); return out;}//在里面实例话 调用函数void output(ostream& )const;void input(istream& )const;private:int n;T* element;
};
template<class T>
antidiagonalMatrix<T>::antidiagonalMatrix(int n){this->n=n;element = new  T[n];}
template<class T>
antidiagonalMatrix<T>::~antidiagonalMatrix(){delete [] element;
}template<class T>
void
antidiagonalMatrix<T>::input(istream & in) const{//for(int i=0;i<n;i++)in>>element[i];
}
template<class T>
void
antidiagonalMatrix<T>::output(ostream& out) const{//for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(i+j!=n-1) // i,j 都是0 开始 -2 cout<<0<<' ';else cout<<element[i]<<' ';cout<<endl;}
}
int main(){
antidiagonalMatrix<int> a(4);cin>>a;cout<<a;return 0;
}

5)

存 O(n)

取? 打印是(n^2)

7.36

1)

T(i,j) == T(i-1,j-1). 其实就是平移到左上角那一个元素(每一条斜的平行线都是相同元素值)

-->递归到 第一行和第一列 的元素  ,而又重合了一个

所以2n-1

2)

按行来

3)

#include<iostream>
using  namespace std;
template<class T>
class toeplitzMatrix{public:toeplitzMatrix(int n=0);~toeplitzMatrix();friend istream& operator>>(istream& in,const toeplitzMatrix<T>& x){x.input(in); return in;}friend ostream& operator<<(ostream& out,const toeplitzMatrix<T>& x){ x.output(out); return out;}//在里面实例话 调用函数void output(ostream& )const;void input(istream& )const;T get(int i,int j) const;void set(int i, int j,T value);T** multiplication(toeplitzMatrix<T>& x);private:int n;T* element;
};
template<class T>
toeplitzMatrix<T>::toeplitzMatrix(int n){this->n=n;element = new  T[2*n-1];}
template<class T>
toeplitzMatrix<T>::~toeplitzMatrix(){delete [] element;
}template<class T>
void
toeplitzMatrix<T>::input(istream & in) const{//for(int i=0;i<2*n-1;i++)in>>element[i];
}
template<class T>
void
toeplitzMatrix<T>::output(ostream& out) const{//for(int i=0;i<n;i++){for(int j=0;j<n;j++)if(i==0) //第一行cout<<element[j]<<' ';else if(j==0)//第一列cout<<element[n+i-1]<<' ';else if(i==j)//主对角线 可以归并到下面两种情况之一 cout<<element[0]<<' ';else if(i>j)//下区cout<<element[n+i-j-1]<<' ';else cout<<element[j-i]<<' ';//主对角线以上cout<<endl;              }
}
template<class T>
T
toeplitzMatrix<T>::get(int i,int j)const {return i>j? element[n+i-j-1]:element[j-i];
}
template<class T>
void
toeplitzMatrix<T>::set(int i,int j,T value){i>j?element[n+i-j-1]=value:element[j-i]=value;
}
template<class T>
T**
toeplitzMatrix<T>::multiplication(toeplitzMatrix<T>& x){T ** result = new T*[n];for(int i=0; i<n;i++)result[i]= new T[n];//初始化int i, j, k, sum ;    for (i = 0; i < n; i++)           {for (j = 0; j <n; j++)   {    sum = 0;for(k=0;k<n;k++){///}    }}return result;}
int main(){
toeplitzMatrix<int> a(4);cin>>a;cout<<a<<endl;a.set(1,1,666);cout<<a;return 0;
}

4)   思路:

找到祖行 也就是第一行或第一列

i>j  (i-j,0) 为祖

j>i  (0,j-i) 为祖

j= i  (0,0 )为祖

然后套公示

7.37

1)

(2(a-1)+1)n-2(1+...+a-1)

= (n-1)*(2n-a) +n

(a<=n)

2)

|i-j| <a

3-4

a,     元素个数是对称分布的{

主对角线下边  =主对角线上边元素 = (n-1)*(2n-a)/2

主对角线  n个元素

}

b,       最少的一条斜线 有 n-a+1个元素

c、    左下角看行 i  来分组(斜线)

右上角 看列 j 来分组

d,        从左下往 主对角线 ,每条斜线多一个元素 直到n-1 个  (i>.j)

于是有:(n-a+1) +[(n-a+1)+1]+....+[(n-a+1)+(a-2-i)] 个元素总和 共有i项

求和  :

(2n-a-i)i/2

     e.      从主对角线往上看斜线 ,每条斜线少一个元素 ,起始为a个元素 (j>i)

于是有:a+a-1+...+(a-j+1) 个元素总和 共有 i项

求和:

(2a-j+1)j/2

f.这些操作其实就是看小组的头成员(斜线分类的第一个元素)

偏移地址就看对应的行或列

总结:

if(i==j)element[(n-1)*(2n-a)/2+i]else if(i>j) element[(2n-a-i)i/2+j]
else element[(2a-j+1)j/2+i]

复杂度为O(1)

5)

不规则数组,O(1)

6)

一维数组应该快一点,但真的有必要吗????????

又难看懂,又要推倒公示 服了邹

7.38

1)略

2) 行列互换

3) 其中一个不为0 相加就不为0

7.39

1)  二维数组: 4+500*4+500*500*4

sparseMatrix : 8+2000*12+8+4

2)

8+12x+8+ >4m+4mn+4

x> (m+mn-1)/3

7.40

cols相当于偏移地址,只要确定了主行+偏移地址就行了

证明:

index1=i1*n+j1;   (n为列数)

index2=i2*n+j2;

当i1=i2   看列偏移    j1<j2  等价于 index1 < index2

当i1<i2  ,右因为 j<n   等价于        index1 < index2

其他情况同理可证

7.41

get:

二分法 ,取arrayList数组中间下标

1,比较行

2,行对上,看列+-偏移量

复杂度logN

set :

1.查找到要插入的位置

2,元素后移插入

复杂度N

7.42

int pre = i*n+j ;cin>>i>>j;
if(i*m+j<=pre|| value == 0) throw....

7.43

用reset

terms.set(i,元素)

逐个复制插入

7.44

1)

m*j+i

2)-3)

一样的,只是映射不一样

7.45

可以设置一个数组 cloStart【】;

cloStart【i】表示第i列第一个元素的索引,用来查找b矩阵的列元素是否为 0

结果矩阵c :

(i,j)     对应矩阵的a i行,b j列  ,至少有一对元素都不为0 ,此位置才不为0

7.46

一样的,映射方式互换一下

7.47

1)

0,2,5,7

2)

用 rowStart【】代替

3)

略,太麻烦了

4)-6)

newSparseMatrix 运行时间是一样的 , 前者空间减少了

7.48

思路跟 7.45一样

7.49

互换行列

7.50

m*12+12x+4> 4m+4mn+4

x> (mn-2m)/3

7.51

就是邻接表

定位到边表对应的行,再数据链表(列) 查找对应

基本方法原理就是链表的插入和遍历

7.52

二维数组,数组元素是个struct,里面有行列等信息

就是把链表换成了指针储存

7.53

十字链表?

一个链表可以行遍历,也可以列遍历 ,并且循环 ;

1)

2)

4+(5*4)*x> 4M+4MN+4

X> (M+MN)/5

3)

先连接 right ,用一个数组记录列下标,再连接down

4)-5)

待调试

ListMatrix<T>::input(istream& in) const{//O(n^2)int i,j,k,col = head->col,row=head->row;T value;int pre;verticalList<T> **colIndex = new verticalList<T> * [col*row/2];for(int i =0;i<col*row/2;i++)//默认最大一半元素非0colIndex[i] = NULL; //存列主顺序指针verticalList<T> *current;current=head;//初始化in>>i>>j>>value;while(i*col+j>pre && value != 0&& i!=-1 && head->value<=col*row&&(i< col &&j<row)){//按行主次序输入,不满足5个条件之一则退出pre= i*col+j;current->right = new verticalList<T>(i,j,value,head);//尾插 循环head->value++;/// for(k=0;k<head->value-1;k++){// 已经储存 value-1个指针 第value个是NULL int index= colIndex[k]->col*row+colIndex[k]->row;if(j*row+i<index){//找到定位copy(colIndex[k],colIndex[head->value],colIndex[k+1]);//向后移break;}}colIndex[k] = current;//这里错了 待调试cout<<head->value<<' '<<k<<' '<<colIndex[k]<<endl;current= current->right;in>>i>>j>>value;}//链接down链表current= head;verticalList<T>* prev=NULL;for(int i=0;i<head->value;i++){current->down = colIndex[i];prev = current;current=current->down;}prev->down = head;
}
template<class T>
void
ListMatrix<T>::output(ostream& out)const{//O(n)verticalList<T> *current =head->right;cout<<"一共有"<<head->value<<"个非0元素"<<endl;cout<<"按行次序遍历:"<<endl;while(current!=head){cout<<current->row<<' '<<current->col<<' '<<current->value<<endl;current=current->right;}cout<<"按列次序遍历:"<<endl;current=head->down;while(current!=head){cout<<current->row<<' '<<current->col<<' '<<current->value<<endl;current=current->down;}
}
template<class T>
void
ListMatrix<T>::Transpose(){ // O(1)verticalList<T> * temp= head->down;head->down= head->right;head->right =temp ;
}
int main(){ListMatrix<int> a(10,10);cin>>a;a.Transpose();cout<<a;
}

第七章总结

本章主要讲了

1   矩阵的表示方法

数组

一维数组映射 (省空间)

行主映射

列主映射

斜线映射(带状,三对角矩阵)

二维数组 (多了 行指针

规则

不规则(每行数组元素个数不相同,)

链表 :

稀疏矩阵等,节省储存方便遍历

2. 特殊矩阵 p157

对角,上下三角矩阵,稀疏矩阵等

这些都可以通过一维数组映射来节省空间

各有优越点 ,对于特殊矩阵

二维数组能节省时间,如get set 都是O(1)

而一维映射,链表能节省空间,但会增加某些方法的时间,也能减少某些方法的时间复杂度

第八章

8.1

【ATAD】

8.2

【SSALC】

8.3

弹夹

8.4

[l1,x,3] [l2,x,2] [l3,x,1] [l4,x,0]  压入递归栈

[l1,x,3] [l2,x,2] [l3,x,1]   弹出 ,l为返回地址,其他为形参或局部变量

[l1,x,3] [l2,x,2]

[l1,x,3]

8.5-8.6

略 ,道理都是一样的

8.7

derivedArrayStack没写,基类懒得找了

思路应该差不多

#include<iostream>
using namespace std;
class illegaParameterValue{public:illegaParameterValue(): message("Stack Empty!"){}illegaParameterValue(char * theMessage){message = theMessage;}void outputMessage(){ cout<< message<<endl;}private:string message;
};
template<class T>
class arrayStack;template<class T>
class stack{public:virtual ~stack(){}virtual bool empty() const =0;virtual int size() const =0; //当前栈中元素个数virtual T& top() =0;//返回栈顶元素引用virtual void pop() =0;virtual void push(const T& theElement ) =0;virtual void input()  = 0;//          输入virtual void output()  =0;//转为合适的输出串virtual void HalfStack(arrayStack<T>& b) =0;//分为两半 virtual void MergeStack(arrayStack<T>& b) = 0;//合并两个栈 相对顺序不变 第二个栈为顶部
};template<class T>
class arrayStack:public stack<T>{public:arrayStack(int init =10);~arrayStack(){delete [] stack;}bool empty()const {return stackTop == -1;}//因为索引 0 为第一个元素int size()const {return stackTop +1;}T& top();void pop();void push(const T& theElement);void input() ;void output() ;void HalfStack(arrayStack<T>& b);void MergeStack(arrayStack<T>& b);void  ChangeArray();private: int stackTop;//栈顶     +1 = 当前元素个数int arrayLength;//总容量T *stack;
};
template<class T>
arrayStack<T>::arrayStack(int init){if(init<=0)throw illegaParameterValue();arrayLength = init;stack = new T[arrayLength];stackTop = -1;
}
template<class T>
T&
arrayStack<T>:: top(){if(empty())throw illegaParameterValue();return stack[stackTop];
}
template<class T>
void
arrayStack<T>::pop(){if(empty())throw illegaParameterValue();stack[stackTop--].~T();
}
template<class T>
void
arrayStack<T>::ChangeArray(){T *temp = new T [arrayLength*2];copy(stack,stack+arrayLength-1,temp);//复杂度 O(arraylength)delete [] stack;arrayLength *=2;stack = temp;
}
template<class T>
void
arrayStack<T>::push(const T& theElement){if(stackTop == arrayLength-1){ChangeArray();//翻倍}stack[++stackTop]= theElement;
}
template<class T>
void
arrayStack<T>:: input(){T temp;char a;cout<<"是否输入数据(Y or y)"<<endl;cin>>a;while(a=='Y'||a=='y'){cin>>temp;push(temp);cin>>a;}
}
template<class T>
void
arrayStack<T>::output(){for(int i =0; i<=stackTop;i++){cout<<stack[i]<<' ';}cout<<endl;
}
template<class T>
void
arrayStack<T>:: HalfStack(arrayStack<T>& b){if(stackTop<1)throw illegaParameterValue();copy(stack+(stackTop+1)/2,stack+stackTop+1,b.stack);b.stackTop=stackTop/2;stackTop=(stackTop-1)/2;
}
template<class T>
void
arrayStack<T>::MergeStack(arrayStack<T>& b) {if(stackTop+b.stackTop+2>=arrayLength)ChangeArray();copy(b.stack,b.stack+b.stackTop+1,stack+stackTop+1);stackTop += b.stackTop+1;
}
int main(){try{arrayStack<int> a(10),b(10);a.push(666);a.push(2000);b.push(999);b.push(222);a.output();b.output();a.MergeStack(b);a.output();}catch(illegaParameterValue e) {e.outputMessage();return 1;}return 0;
}

7.8

个别push,数组已满,要扩容复制,为O(栈的大小)

不可能每次push操作都要扩张

平摊分析中

执行一系列数据结构操作所需要的时间是通过执行的所有操作求平均而得出的。平摊分析可以用来证明在一系列操作中,通过对所有操作求平均之后,即使其中单一的操作具有较大的代价,平均代价还是很小的。

平摊分析不牵涉到概率平摊分析保证在最坏情况下,每个操作具有的平均性能。

#算法 平摊分析——一种特殊的分析方法_Franklins_Fan的博客-CSDN博客

8.9

template<class T>
void
arrayStack<T>::pop(){if(empty())throw illegaParameterValue();if(stackTop< arrayLength/4){T *temp = new T [arrayLength/2];copy(stack,stack+stackTop,temp);delete stack;stack =temp;arrayLength/=2;}else stack[stackTop--].~T();
}

证明一样的

8.10

stackWithArrayList 在自己类中实现方法,可以不用多余步骤(如判断)

dervedArrayStack 可以直接使用基类方法,避免重写,但效率欠佳

8.11

以前好像写过,这里就不写了 一搜就有

注意: 当任意一栈顶+1(或-1) == 另一栈顶时 或  等于0 或等于 arrayLength-1 时

则已满

top1从左向右,top2从右向左

8.12-8.13

linkedStack

#include<iostream>
#include<string>
#include<sstream>
using namespace std;
class arrayList;
class illegaParameterValue{public:illegaParameterValue(): message("Illegal value"){}illegaParameterValue(char * theMessage){message = theMessage;}void outputMessage(){ cout<< message<<endl;}private:string message;
};
template<class T>
class linkedStack;
template<class T> // 抽象类
class stack{public:virtual ~stack(){}virtual bool empty() const =0;virtual int size() const =0; //当前栈中元素个数virtual T& top() =0;//返回栈顶元素引用virtual void pop() =0;virtual void push(const T& theElement ) =0;virtual void input()  = 0;//          输入virtual void output()  =0;//转为合适的输出串virtual void HalfStack(linkedStack <T>& b) =0;//分为两半 virtual void MergeStack(linkedStack <T>& b) = 0;//合并两个栈 相对顺序不变 第二个栈为顶部
};
template<class T>
struct chainNode{//结构体也能构造 成员,函数T element;chainNode<T> *next;chainNode(){}chainNode(const T& element){ this->element= element;}chainNode(const T& element,chainNode<T> * next){this->element= element;this->next=next;}
};
template<class T>
class linkedStack : public stack<T>{//抽象类的派生类public:linkedStack(int inin = 10);linkedStack(const linkedStack<T>&);//0~linkedStack();
/bool empty() const {return stackSize == 0;}int size() const {return stackSize ;} void pop();chainNode<T>  popNode();void pushNode(chainNode<T> *theNode);void push(const T& theElement);T& top();void input()  ;void output() ;void HalfStack(linkedStack <T>& b) ;void MergeStack(linkedStack <T>& b) ;//friend ostream& operator<<(ostream& out,const linkedStack<T>& x){ x.output(out); return out;}protected:chainNode<T>* stackTop;int stackSize;
};
template<class T>
linkedStack<T>::~linkedStack(){while(stackTop != NULL){chainNode<T>* deleteNode = stackTop;stackTop=stackTop->next;delete deleteNode;}
}
template<class T>linkedStack<T>:: linkedStack(int init){stackTop = NULL;stackSize =0; }
template<class T>
void
linkedStack<T>::pop(){if(stackSize== 0)throw illegaParameterValue();chainNode<T>* nextNode=stackTop->next;delete stackTop;stackTop = nextNode;stackSize--;
}
template<class T>
chainNode<T>
linkedStack<T>::popNode(){if(stackSize== 0)throw illegaParameterValue();chainNode<T>* tempNode=stackTop;stackTop = stackTop->next;stackSize--;return *tempNode;}
template<class T>
void
linkedStack<T>::pushNode(chainNode<T> *theNode){theNode->next=stackTop->next;stackTop->next = theNode;
}
template<class T>
void
linkedStack<T>::push(const T& theElement){stackTop = new chainNode<T>(theElement,stackTop);stackSize++;
}
template<class T>
T&
linkedStack<T>::top(){return stackTop->element;
}
template<class T>
void
linkedStack<T>:: input() {T temp;char a;cout<<"是否输入数据(Y or y)"<<endl;cin>>a;while(a=='Y'||a=='y'){cin>>temp;push(temp);cin>>a;}}
template<class T>
void
linkedStack<T>::output(){for(chainNode<T>* currentNode =stackTop;currentNode!= NULL;currentNode=currentNode->next)cout<<currentNode->element <<' ';cout<<endl;
}
template<class T>
void
linkedStack<T>:: HalfStack(linkedStack <T>& b) {chainNode<T>* current=stackTop;for(int i=0;i<stackSize/2-1;i++){current=current->next;}b.stackTop=current->next;current->next = NULL;b.stackSize=stackSize;stackSize/=2;b.stackSize-=stackSize;
}
template<class T>
void
linkedStack<T>::MergeStack(linkedStack<T>& b){chainNode<T>* current=b.stackTop;for(int i=0;i<b.stackSize-1;i++)current =current->next;current->next=stackTop;stackTop=b.stackTop;stackSize+=b.stackSize;b.stackTop= NULL;b.stackSize= 0;
}              int main(){linkedStack<int>  a,b;a.input();a.HalfStack(b);a.output();b.output();return 0;
}

8.14

有些方法简单很多,只需要改变指向就行了

不会容量加倍,因为是链表

8.15

#include<iostream>
#include<string>
using namespace std;
bool check(string s){
//遍历一次 string::iterator i=s.begin();int a=0,b=0;while(i!=s.end())if(*i=='(')a++;else if( *i==')')b++;if(a!=b)return false;return true;}int main(){string s;cin>>s;cout<<check(s)<<endl;
}

8.16

‘(’  从右往左遍历

‘)’ 从左往右遍历,两个stack

void printMatchendPairs(string s){//8.17arrayStack<int> a,b;int length= (int) s.size();for(int i=0,j=length-1;i<length;i++,j--){if(s.at(j)=='(' )a.push(j);if(s.at(i)==')')b.push(i);}if(a.size()!=b.size())cout<<"UN equal"<<endl;int min= a.size()>b.size()?b.size():a.size();for(int i=0;i<min;i++){cout<<"("<<a.top()<<b.top()<<")"<<' '<<endl;a.pop();b.pop();}
}
int main(){string s;cin>>s;printMatchendPairs(s);return 0;
}

8.17

多用几个栈呗

8.18

x->y

x->z

y->z

x->y

z->x

z->y

x->y

x->z

y->z

y->x

z->x

y->z

x->y

x->z

y->z

8.19

对于n==1 :

进入hanoi (1) ,由于n-1==0 进入两个内部循环(2)都没有执行具体步骤就返回了

对于n==2:

进入hanoi(1),n-1 == 1 进入内部循环(2) 1-1=0 ,进入内部循环(3)不满足返回

1->2->3->2->1> ,这时 已经全部移动到盘子2了

然后进入第一层hanoi的第二个内部循环,重复,全部移动到盘子2了

对于n==n:

进入n+1层hanoi不满足返回

1->2->...->n+1->n->n-1->...->1

8.20:

被移动的就是当前n的编号,多输出一个n就行了

8.21:

template<class T>
void
arrayStack<T>::showState(){for(int i=stackTop;i>=0;i--){cout<<stack[i]<<' ';}cout<<endl;for(int i=0;i<40000;i++)//睡眠;
}

8.22

不用大的在下面

n+n-1 == 2n-1

void haha(int n,char x,char y,char z){for(int i=0;i<n-1;i++){printf("%c->%c\n",x,z);}printf("%c->%c\n",x,y);for(int i=0;i<n-1;i++)printf("%c->%c\n",z,y);}

8.23

可以减少 内层循环的次数

当为n-1时n-1个次大盘子直接移动到到n-1个中转站 ,最大的移动到目标盘子,再将n-1个中转移动到目标

n-1 +1 +n-1== 2n-1

8.24

两个缓冲不行

8.25

都是[0,k-1]

分k=1时,和最好情况时

8.26

1)不能,如8.24

2) 是最少的,因为有n个逆序(相对输出的来说),且k是最低的轨道个数,失败k就会++

8.27

加一条判断 当stacktop==si-1时 则满,此栈不能再使用,另寻它栈

8.28

遍历检查时,调用show()

8.29

int group[n];
bool flag[n];
for(int i=0;i<n;i++)//匹配网组,下标匹配值
if(i%2==0)group(net[i])=net[i+1];else group(net[i])=net[i-1];for(int i=0;i<n;i++)flag[i]=false;....for循环判断 {
...
push(i),flag[i]=true;if(flag[i]&&flag[flag[i]])return false;}

一样大小的栈;

8.30

等价离线类 要点:

n个元素 -->n个关系表

种子数组out【n】

默认从第一个开始为种子,入等价栈

等价栈 者  ->要加入list【入元素】表中全部内容

直到栈为空(无新关联元素加入) 输出的就是一个等价类

out数组全为true则遍历完毕

8.31

///书上打的 不知道哪里错了 说内存溢出int n,r;cout<<"enter number of elements"<<endl;cin>>n;if(n<2){cout<<"Too few elements"<<endl;return 1;}cout<<"enter number of relations"<<endl;cin>>r;if(r<1){cout<<"too few relations"<<endl;return 1;}arrayStack<int> *list = new arrayStack<int> [n+1];int a,b;//关系队rfor(int i=1;i<=r;i++){//几个元素 几个表cout<<"enter next relation/pair"<<endl;cin>>a>>b;if( (a<1||a>n)|| (b<1||b>n) )throw  illegaParameterValue();list[a].push(b);list[b].push(a);}arrayStack<int> unprocessedList; //等价类临时栈bool *out =new bool[n+1];//种子数组 当且仅当全部为true 为结束for(int i=1; i<=n;i++)out[i]= false;//步骤2for( int i=1;i<=n;i++)if(!out[i] ){cout<<"next class is:"<<i<<' ';out[i] =true;unprocessedList.push(i);//先压入当前种子while(!unprocessedList.empty()){int j= unprocessedList.top();unprocessedList.pop();//临时栈元素出栈while(!list[j].empty()){// 入栈者 ?->要加入list【入元素】表中全部内容int q=list[j].top();list[j].pop(); //相当于移动到临时栈if(!out[q]){cout<<q<<' ';out[q]=true;unprocessedList.push(q);}}}cout<<endl;}cout<<"end of list of equivalence classes "<<endl;
 int a,b;//关系队rfor(int i=1;i<=r;i++){//几个元素 几个表cout<<"enter next relation/pair"<<endl;cin>>a>>b;if( (a<1||a>n)|| (b<1||b>n) )throw  illegaParameterValue();list[a].push(b);list[b].push(a);}

8.32

具体实现方法不一样,但调用方法一样(都是调用成员函数empty()等)

数组肯定快一点

8.33

C++控制输出的字体颜色_幻欢子-CSDN博客_c++字体颜色

C++中发声函数Beep详解_v1t1p9hvbd的博客-CSDN博客

maze

#include <iostream>
#include "windows.h"//macOs下没有
struct position{int row;int clo;
};
arrayStack<position> *path ;//路线栈
int **maze;//矩阵
void welcome(){// Beep(523,400);//do // SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED |//  FOREGROUND_BLUE);//设置红色和蓝色相加//        cout<<"     -----------------"<<endl;//        cout<<"     欢迎来到迷宫小游戏"<<endl;//        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN)//     ;//设置绿色//      cout<<endl<<endl<<"     按任意键开始输入迷宫"<<"- -"<<endl; //      getchar();//        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN |//     FOREGROUND_BLUE);//设置绿色和蓝色相加
}
void inputMaze(){//出口默认size,size cout<<"enter Maze size"<<endl;int size,i,j;cin>>size;if(size<1)//cout<<"error"<<endl; maze = new int*[size+2]; //多申请2维 ,最外一圈栅栏 for(int i=0;i<=size+1;i++){maze[i]= new int[size+2];}for(int i=0;i<=size+1;i++)for(int j=0;j<=size+1;j++)maze[i][j]=0;for(int i=0;i<=size+1;i++){//围栅栏 maze[0][i]=maze[size+1][i]=1;maze[i][0]= maze[i][size+1]=1;}cout<<"enter Roadblock"<<endl;cin>>i>>j;while(i!=-1){if(i>size+1||i<1||j>size+1||j<1){cout<<"Cross the border ,re enter"<<endl;cin>>i>>j;continue;}maze[i][j]=1;cin>>i>>j;}     for(int i=0;i<=size+1;i++){//show for(int j=0;j<=size+1;j++)cout<<maze[i][j]<<' ';cout<<endl;}cout<<"enter Roadblock"<<endl;}bool findPath(){path = new arrayStack<position>;/书上有懒得复制return true;
}void outputPath(){while(path->size()!=0){cout<<path->top().row<<" "<<path->top().clo<<endl;path->pop();}cout<<"output END"<<endl;
}
int main(){welcome();inputMaze();if(findPath())outputPath();else cout<<"no path"<<endl;return 0;
}

8.34

struct position{int row;int col;
};
position next,here;
int option;
position offset[7];offset[0].row=0;offset[0].col=1;offset[1].row=1;offset[0].col=0;offset[2].row=0;offset[0].col=-1;offset[3].row=-1;offset[0].col=0;offset[4].row=-1;offset[0].col=-1;//左上offset[5].row=-1;offset[0].col=1;//右上offset[6].row=1;offset[0].col=-1;//左下offset[7].row=1;offset[0].col=1;//右下//。。。对于返回下一次移动  if(next.row==here.row)option =2 +next.col-here.col;else if(next.col=here.col)option= 3+next.row-here.row;else if(next.row+1==here.row){if(here.col=next.col+1)option=6;else option=5;}else {if(next.row+1==here.row)option = 8;//所有情况全无else option=7;}

8.35

m^2-1-blocked

8.36

思路应该是这样 ,但哪里错了呢 ,待调试

bool findPath(int i,int j,int size){if(i>size|| j>size || i<1 || j<1 ||maze[i][j]==1)return 0;maze[i][j]=1;//先堵住防止返回if(i==size&&j==size)//到目标点提前结束return 1;//递归部分if( findPath(i,j+1,size) ){cout<<i<<' '<<j<<endl;return 1;}if( findPath(i+1,j,size) ){cout<<i<<' '<<j<<endl;return 1;}if( findPath(i,j-1,size) ){cout<<i<<' '<<j<<endl;return 1;}if( findPath(i-1,0,size) ){cout<<i<<' '<<j<<endl;return 1;}}

8.37

网站呢 ,也没说 服了

8.38

从右往左遍历data

若为空则压入当前

循环 比较当前下标元素的值和栈顶下标元素的值   ,出栈直到大于当前或为空,押入当前

,由于从右向左,就是左边最靠近且大于的值

注意:栈a压入的是下标

最终a栈剩下的就是不符合条件的,由于一开始已经全部初始化为-1,无需弹出操作

nt main(){int data[]={6,2,3,1,7,4};int n=sizeof(data)/sizeof(data[0]);int lastAsBig[n];for(int i=0;i<n;i++)lastAsBig[i]=-1; //全部初始化为-1 arrayStack<int> a(n);for(int i=n-1;i>=0;i--){if(a.empty()){a.push(i);//押入下标continue;}if(data[a.top()]>data[i])a.push(i);else{while(!a.empty()&&data[a.top()]<data[i]){lastAsBig[a.top()]=i;a.pop();}a.push(i);}}for(int i=0;i<n;i++)cout<<lastAsBig[i]<<' ';cout<<endl;}

第八章总结

本章主要讲了栈的形式,结构,应用等

a        LIFO

b   分为 数组和链表两种实现方法,总体性能来讲还是数组占优,因为链表还多了很多指针

应用:

hanoi

列车调度

找迷宫

这些都可以用栈的思想来实现,也可以用递归。

感觉有一种分而治之的思想,向下延伸,不行再退回前一步

感悟:

界面的设计很重要,如何设计欢迎界面,如何播放音乐,输出图片?

这些都是要学习的,可能比程序本身更重要更繁琐

今天20岁咯,越努力越幸运

-----21/10/19

  第九章

9.1

DATA

9.2

医院挂号

9.3

双开门电梯

9.4

离线等价类等价栈加入元素时

9.5

1)  合并待调试

#include<iostream>
using namespace std;
template<class T>
class arrayQueqe;
template<class T>
class Queqe{public:virtual ~Queqe(){}virtual bool empty() const =0;virtual int size() const =0;virtual T& Front()=0;virtual T& Back()=0;virtual void pop()=0;virtual void push(const T& theElement) =0;virtual void input()=0;virtual void output()=0;virtual void HalfQueqe(arrayQueqe<T>& b) =0;//分为两半virtual void MergeQueqe(arrayQueqe<T>& b)=0;//合并
};template<class T>
class arrayQueqe:public Queqe<T>{public:arrayQueqe(int init =10);~arrayQueqe(){delete [] Queqe;}bool empty()const {return front==back;}int size()const ;void pop();void push(const T& theElement);void  ChangeArray();T& Front() {return front;}virtual T& Back() {return back;}void input();void output();void HalfQueqe(arrayQueqe<T>& b);void MergeQueqe(arrayQueqe<T>& b);private:int front;int back;int arrayLength;T *Queqe;
};
template<class T>
arrayQueqe<T>::arrayQueqe(int init){front=back=0;//[front+1] 是第一个元素的位置Queqe = new T[init];arrayLength = init;
}
template<class T>
int
arrayQueqe<T>::size()const{if(back>=front)return back-front;elsereturn back+arrayLength-front;
}
template<class T>
void
arrayQueqe<T>::pop(){if(front== back){cout<<"error!";exit(1);}front=(front+1)%arrayLength;Queqe[front].~T();
}
template<class T>
void
arrayQueqe<T>::push(const T& theElement){if( (back+1)%arrayLength== front)ChangeArray();back=(back+1)%arrayLength;Queqe[back]= theElement;
}
template<class T>
void
arrayQueqe<T>::ChangeArray(){T* newQueqe= new T[2*arrayLength];int start=(front+1)&arrayLength;//第一个元素的位置if(start<2){ //说明front为0 并没有循环数组copy(Queqe+start,Queqe+start+arrayLength-1,newQueqe);}else {copy(Queqe+start,Queqe+arrayLength,newQueqe);copy(Queqe,Queqe+back+1,newQueqe+arrayLength-start);}front= 2*arrayLength-1;//默认新数组最后一个 第一个下标为【0】back=arrayLength-2; //arrayLength-1-1arrayLength*=2;delete[]Queqe;Queqe = newQueqe;
}
template<class T>
void
arrayQueqe<T>::input(){T value;char c;cout<<"是否输入数据(Y|y)"<<endl;cin>>c;while(c=='y'||c=='Y'){cout<<"请输入数据"<<endl;cin>>value;push(value);cout<<"是否输入数据(Y|y)"<<endl;cin>>c;}
}
template<class T>
void
arrayQueqe<T>::output(){if(back>=front){for(int i=front+1;i<=back;i++)cout<<Queqe[i]<<' ';}else {for(int i=front+1;i<arrayLength;i++)cout<<Queqe[i]<<' ';for(int i=0;i<=back;i++)cout<<Queqe[i]<<' ';}cout<<endl;}
template<class T>
void
arrayQueqe<T>::HalfQueqe(arrayQueqe<T>& b){arrayQueqe<T>* temp=new arrayQueqe<T>(arrayLength);int start=front+1;if(back>=front){while(start<=back){temp->push(Queqe[start++]);if(start>back)break;b.push(Queqe[start++]);}}else {while(start<arrayLength){//插入后半段temp->push(Queqe[start++]);if(start>=arrayLength)break;b.push(Queqe[start++]);}//前面一段if( (arrayLength-1-front) %2==0)//下一个为奇 插入tempfor(int i=0;i<=back;){temp->push(Queqe[i++]);if(i>back)break;b.push(Queqe[i++]);}elsefor(int i=0;i<=back;){b.push(Queqe[i++]);if(i>back)break;temp->push(Queqe[i++]);}}delete[] Queqe;Queqe=temp->Queqe;back=temp->Back();front=temp->Front();cout<<endl;
}
template<class T>
void
arrayQueqe<T>::MergeQueqe(arrayQueqe<T>& b){//待调试int newSize=size()+b.size()+1;arrayQueqe<T>* temp=new arrayQueqe<T>(newSize);int i=front+1,j=b.front+1;int i1=0,j1=0;while(i1==back+1||i==back+1||j==b.back+1||j1==b.back+1){if(back>=front){temp->push(Queqe[i++]);}else if(i<arrayLength)temp->push(Queqe[i++]);else{temp->push(Queqe[i1++]);}if(b.back>=b.front){temp->push(Queqe[j++]);}else if(j<arrayLength)temp->push(Queqe[j++]);else{temp->push(Queqe[j1++]);}}//插入剩下的  i==back 或 i1==back&&(i==length)if(i>back+1){while(i<arrayLength)temp->push(Queqe[i++]);while(i1<=back)temp->push(Queqe[i1++]);}if(j>b.back+1){while(j<b.arrayLength)temp->push(Queqe[j++]);//尾部加入while(j1<=back)temp->push(Queqe[j1++]);}temp->output();}
int main(){arrayQueqe<int> a(3),b;a.push(1);a.push(2);a.push(3);b.push(666);a.MergeQueqe(b);cout<<endl;return 0;
}

2)

差不多

9.6

肯定循环数组效率高 插入删除为O(1) 即使少数为O(元素个数)

9.7

“队列的容量与数组大小相同?”

那   初始值 quenueSize = 0;

Back=(quenueFront+quenueSize-1)%quenueSize;

9.8

相当于设置一个哨兵;

初始值 bool lastop= 0;(相当于pop了一次 ,一定不为满 ),若push 设置为1 pop为0

if(front==back && lastop==0)

为空

if(front==back && lastop==1)

为满

9.9

#include<iostream>
using namespace std;
template<class T>
class arraydeque;
template<class T>
class deque{public:virtual ~deque(){}virtual bool empty() const =0;virtual int size() const =0;virtual T& Front()=0;virtual T& Back()=0;virtual void pop_front()=0;virtual void push_front(const T& theElement) =0;virtual void pop_back()=0;virtual void push_back(const T& theElement) =0;};template<class T>
class arraydeque:public deque<T>{public:arraydeque(int init =10);~arraydeque(){delete [] deque;}bool empty()const {return front==back;}int size()const ;void pop_front();void push_front(const T& theElement) ;//0void pop_back();//0void push_back(const T& theElement) ;void  ChangeArray();T& Front() {return front;}T& Back() {return back;}void output();private:int front;int back;int arrayLength;T *deque;
};
template<class T>
void
arraydeque<T>::output(){if(back>=front){for(int i=front+1;i<=back;i++)cout<<deque[i]<<' ';}else {for(int i=front+1;i<arrayLength;i++)cout<<deque[i]<<' ';for(int i=0;i<=back;i++)cout<<deque[i]<<' ';}cout<<endl;}
template<class T>
arraydeque<T>::arraydeque(int init){front=back=0;//[front+1] 是第一个元素的位置deque = new T[init];arrayLength = init;
}
template<class T>
int
arraydeque<T>::size()const{if(back>=front)return back-front;elsereturn back+arrayLength-front;
}
template<class T>
void
arraydeque<T>::pop_front(){if(front== back){cout<<"error!";exit(1);}front=(front+1)%arrayLength;deque[front].~T();
}
template<class T>
void
arraydeque<T>::pop_back(){if(front== back){cout<<"error!";exit(1);}back=  back-1<0?arrayLength-1:back-1;
}
template<class T>
void
arraydeque<T>::push_front(const T& theElement){if( (back+1)%arrayLength== front)ChangeArray();if( front<back || front==arrayLength-1){//没循环 或下一个是【0】copy(deque+(front+1)%arrayLength,deque+back+1,deque+(front+2)%arrayLength);deque[(front+1)%arrayLength]=theElement;back++;}   else {copy(deque,deque+back+1,deque+back+2);//移动前半部分deque[0]=deque[arrayLength-1];//最后一个移到【0】copy(deque+front+1,deque+arrayLength-1,deque+front+2);//移动后半部分deque[front+1]=theElement;//赋值}}
template<class T>
void
arraydeque<T>::push_back(const T& theElement){if( (back+1)%arrayLength== front)ChangeArray();back=(back+1)%arrayLength;deque[back]= theElement;
}
template<class T>
void
arraydeque<T>::ChangeArray(){T* newdeque= new T[2*arrayLength];int start=(front+1)&arrayLength;//第一个元素的位置if(start<2){ //说明front为0 并没有循环数组copy(deque+start,deque+start+arrayLength-1,newdeque);}else {copy(deque+start,deque+arrayLength,newdeque);copy(deque,deque+back+1,newdeque+arrayLength-start);}front= 2*arrayLength-1;//默认新数组最后一个 第一个下标为【0】back=arrayLength-2; //arrayLength-1-1arrayLength*=2;delete[]deque;deque = newdeque;
}int main(){arraydeque<int> a(3),b;a.push_back(5);a.push_back(6);a.push_front(666);a.push_front(666);a.pop_back();a.output();cout<<endl;return 0;
}

9.10-9.11

不太懂继承 ,直接调用基类arrayDeque的方法就行了,好像也不用新成员

复杂度就是对应方法的复杂度

#include<iostream>
using namespace std;
template<class T>
class arraydeque;
template<class T>
class deque{public:virtual ~deque(){}virtual bool empty() const =0;virtual int size() const =0;virtual T& Front()=0;virtual T& Back()=0;virtual void pop_front()=0;virtual void push_front(const T& theElement) =0;virtual void pop_back()=0;virtual void push_back(const T& theElement) =0;};
template<class T>
class stack{public:virtual ~stack(){}virtual bool empty() const =0;virtual int size() const =0; //当前栈中元素个数virtual T& top() =0;//返回栈顶元素引用virtual void pop() =0;virtual void push(const T& theElement ) =0;virtual void input()  = 0;//          输入virtual void output()  =0;//转为合适的输出串
};template<class T>
class arraydeque:public deque<T>{public:arraydeque(int init =10);~arraydeque(){delete [] deque;}bool empty()const {return front==back;}int size()const ;void pop_front();void push_front(const T& theElement) ;//0void pop_back();//0void push_back(const T& theElement) ;void  ChangeArray();T& Front() {return front;}T& Back() {return back;}void output();private:int front;int back;int arrayLength;T *deque;
};
template<class T>
class dequeStack:public arraydeque<T>{//多重继承 逗号隔开//直接调用基类方法就行了};
template<class T>
void
arraydeque<T>::output(){if(back>=front){for(int i=front+1;i<=back;i++)cout<<deque[i]<<' ';}else {for(int i=front+1;i<arrayLength;i++)cout<<deque[i]<<' ';for(int i=0;i<=back;i++)cout<<deque[i]<<' ';}cout<<endl;}
template<class T>
arraydeque<T>::arraydeque(int init){front=back=0;//[front+1] 是第一个元素的位置deque = new T[init];arrayLength = init;
}
template<class T>
int
arraydeque<T>::size()const{if(back>=front)return back-front;elsereturn back+arrayLength-front;
}
template<class T>
void
arraydeque<T>::pop_front(){if(front== back){cout<<"error!";exit(1);}front=(front+1)%arrayLength;deque[front].~T();
}
template<class T>
void
arraydeque<T>::pop_back(){if(front== back){cout<<"error!";exit(1);}back=  back-1<0?arrayLength-1:back-1;
}
template<class T>
void
arraydeque<T>::push_front(const T& theElement){if( (back+1)%arrayLength== front)ChangeArray();if( front<back || front==arrayLength-1){//没循环 或下一个是【0】copy(deque+(front+1)%arrayLength,deque+back+1,deque+(front+2)%arrayLength);deque[(front+1)%arrayLength]=theElement;back++;}   else {copy(deque,deque+back+1,deque+back+2);//移动前半部分deque[0]=deque[arrayLength-1];//最后一个移到【0】copy(deque+front+1,deque+arrayLength-1,deque+front+2);//移动后半部分deque[front+1]=theElement;//赋值}}
template<class T>
void
arraydeque<T>::push_back(const T& theElement){if( (back+1)%arrayLength== front)ChangeArray();back=(back+1)%arrayLength;deque[back]= theElement;
}
template<class T>
void
arraydeque<T>::ChangeArray(){T* newdeque= new T[2*arrayLength];int start=(front+1)&arrayLength;//第一个元素的位置if(start<2){ //说明front为0 并没有循环数组copy(deque+start,deque+start+arrayLength-1,newdeque);}else {copy(deque+start,deque+arrayLength,newdeque);copy(deque,deque+back+1,newdeque+arrayLength-start);}front= 2*arrayLength-1;//默认新数组最后一个 第一个下标为【0】back=arrayLength-2; //arrayLength-1-1arrayLength*=2;delete[]deque;deque = newdeque;
}int main(){
dequeStack<int> a;a.push_back(6);a.push_back(5);a.push_back(666);a.pop_back();a.output();cout<<endl<<a.size();return 0;
}

9.12-9.13

没用基类 ,懒得找了 ,合并和插入以前章节写过不写了

#include<iostream>
using namespace std;
template<class T>
struct chainNode{T element;chainNode<T> *next;chainNode(){}chainNode(const T& element){ this->element= element;}chainNode(const T& element,chainNode<T> * next){this->element= element;this->next=next;}
};
template<class T>
class Queqe{public:virtual ~Queqe(){}virtual bool empty() const =0;virtual int size() const =0;// virtual T& Front()=0;// virtual T& Back()=0;virtual void pop()=0;virtual void push(const T& theElement) =0;virtual void input()=0;virtual void output()=0;// virtual void HalfQueqe() =0;//分为两半// virtual void MergeQueqe()=0;//合并
};
template<class T>
class linkedQueue:public Queqe<T>{//从前向后 back指向最后一个节点 ,back-》next 为NULLpublic:linkedQueue();~linkedQueue();bool empty() const{return theFront==theBack;}int size() const{return listSize;}// T& Front(){}// T& Back(){}void pop();void push(const T& theElement) ;void input();void output();private:chainNode<T> *theFront;chainNode<T> *theBack;int listSize;
};
template<class T>
linkedQueue<T>::linkedQueue(){theFront=theBack=NULL;listSize =0;
}
template<class T>
linkedQueue<T>::~linkedQueue(){chainNode<T> * dele=theFront;while(theFront != NULL){//不为空theFront=theFront->next;delete dele;dele = theFront;}
}
template<class T>
void
linkedQueue<T>::push(const T& theElement){chainNode<T> *newNode=  new chainNode<T>(theElement,NULL);if(listSize==0)theFront =newNode;else theBack->next = newNode;theBack= newNode;listSize++;
}
template<class T>
void
linkedQueue<T>::pop(){if(listSize ==0){cout<<"error!"<<endl;exit(1);}chainNode<T> *nextNode= theFront->next;delete theFront;theFront= nextNode;listSize--;}
template<class T>
void
linkedQueue<T>::output(){chainNode<T> *currentNode=theFront;while(currentNode !=NULL){cout<<currentNode->element<<' ';currentNode=currentNode->next;}cout<<endl;
}
template<class T>
void
linkedQueue<T>::input(){T value;char c;cout<<"是否输入数据(Y|y)"<<endl;cin>>c;while(c=='y'||c=='Y'){cout<<"请输入数据"<<endl;cin>>value;push(value);cout<<"是否输入数据(Y|y)"<<endl;cin>>c;}
}
int main(){linkedQueue<int> a;a.push(5);a.push(666);a.push(3);a.pop();a.output();return 0;}

9.14

测试总时间模板

#include<iostream>
#include<time.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义0///---------------------------
int main(){long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字long numberRepetitions =0;clock_t startTime= clock();//返回目前为止的时间for(int i=0;i<1000000;i++){// 调用函数  0}long double elapsedMillis= (clock()-startTime)/clocksPerMillis;cout<<elapsedMillis<<endl;return 0;
}
#include<iostream>
#include<time.h>
#define MAX_ 1000
using namespace std;
// 测试的函数定义
#include<iostream>
using namespace std;
template<class T>
class arrayQueqe;
template<class T>
class Queqe{//  public://   virtual ~Queqe(){}//   virtual bool empty() const =0;//   virtual int size() const =0;//   virtual T& Front()=0;//   virtual T& Back()=0;//   virtual void pop()=0;//   virtual void push(const T& theElement) =0;//   virtual void input()=0;//   virtual void output()=0;//   virtual void HalfQueqe(arrayQueqe<T>& b) =0;//分为两半//   virtual void MergeQueqe(arrayQueqe<T>& b)=0;//合并
};template<class T>
class arrayQueqe:public Queqe<T>{public:arrayQueqe(int init =10);~arrayQueqe(){delete [] Queqe;}bool empty()const {return front==back;}int size()const ;void pop();void push(const T& theElement);void  ChangeArray();T& Front() {return front;}virtual T& Back() {return back;}void input();void output();void HalfQueqe(arrayQueqe<T>& b);void MergeQueqe(arrayQueqe<T>& b);private:int front;int back;int arrayLength;T *Queqe;
};
template<class T>
arrayQueqe<T>::arrayQueqe(int init){front=back=0;//[front+1] 是第一个元素的位置Queqe = new T[init];arrayLength = init;
}
template<class T>
int
arrayQueqe<T>::size()const{if(back>=front)return back-front;elsereturn back+arrayLength-front;
}
template<class T>
void
arrayQueqe<T>::pop(){if(front== back){cout<<"error!";exit(1);}front=(front+1)%arrayLength;Queqe[front].~T();
}
template<class T>
void
arrayQueqe<T>::push(const T& theElement){if( (back+1)%arrayLength== front)ChangeArray();back=(back+1)%arrayLength;Queqe[back]= theElement;
}
template<class T>
void
arrayQueqe<T>::ChangeArray(){T* newQueqe= new T[2*arrayLength];int start=(front+1)&arrayLength;//第一个元素的位置if(start<2){ //说明front为0 并没有循环数组copy(Queqe+start,Queqe+start+arrayLength-1,newQueqe);}else {copy(Queqe+start,Queqe+arrayLength,newQueqe);copy(Queqe,Queqe+back+1,newQueqe+arrayLength-start);}front= 2*arrayLength-1;//默认新数组最后一个 第一个下标为【0】back=arrayLength-2; //arrayLength-1-1arrayLength*=2;delete[]Queqe;Queqe = newQueqe;
}
template<class T>
void
arrayQueqe<T>::input(){T value;char c;cout<<"是否输入数据(Y|y)"<<endl;cin>>c;while(c=='y'||c=='Y'){cout<<"请输入数据"<<endl;cin>>value;push(value);cout<<"是否输入数据(Y|y)"<<endl;cin>>c;}
}
///---------------------------
int main(){arrayQueqe<int> a(100000);long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000;  //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字long numberRepetitions =0;clock_t startTime= clock();//返回目前为止的时间for(int i=0;i<1000000;i++){a.push(1);}for(int i=0;i<1000000;i++){a.pop();}long double elapsedMillis= (clock()-startTime)/clocksPerMillis;cout<<elapsedMillis<<endl;return 0;
}

链表的

数组的

初始化为10 和100000大小一样的

结论: 可以看到数组比链表快了近 5倍

9.15

说实话,感觉题目内容很重复,就不写了

只是形参是个节点,方法内不用new

9.16-18

不写了  第六章全写过,细节改一下罢了

9.19

电路布线: 选择移动到下一个位置 ,上下左右并无特殊要求,可以用栈

图元识别: 同理可换

9.20

两个轨道不行

9.21

可以 ,k条轨道上线是k个序列

假设k个全部递增  1,2,3,..k

2至k全部安排到k-1条缓冲带   然后依次输出

9.22

没看明白什么意思,si是给定的吗,那加条件就行了

9.23

#include<iostream>
using namespace std;
bool showTrack(int length,int tracks,int *carArray){int lastCar[tracks+1];int whichTrack[length+1];for(int i=0; i<=tracks;i++)lastCar[i]=0;for(int i=0;i<=length;i++)whichTrack[i]=0;int k=1;//当前要出编号  int theCar;for(int i=1;i<=length;i++){cout<<i<<"----"<<k<<endl;if(carArray[i]!=k){theCar=carArray[i];int  bestTrack=0,bestLast=0;//扫描轨道。。。。 for(int i=1;i<=tracks;i++){if(lastCar[i]!=0){int lastCarNUM=lastCar[i];if(theCar>lastCarNUM&& lastCarNUM>bestLast){bestLast =lastCarNUM;bestTrack =i;}}else if(bestTrack== 0)//都不为空 且都不符合才不执行这 ,不然默认选择一个空队列 bestTrack=i;            }if( bestTrack==0)return false;///1 whichTrack[theCar] =bestTrack;lastCar[bestTrack]=theCar;}else {//输出并查看cout<<"outCar:"<<k++<<endl;while( whichTrack[k] != 0 ) {//在缓冲轨道内cout<<"outCar:"<<k<<endl;whichTrack[k++] =0;}}cout<<"show Track:"<<endl;for(int i=1;i<length;i++)cout<<whichTrack[i]<<' ';cout<<endl;}return true;
}int main(){int carArray[]={-1,3,1,7,6,2,8,5,4};int length=sizeof carArray/sizeof carArray[0]-1;cout<<  showTrack(length,3,carArray);return 0;}

9.24

思路一样 , 只是扫描方法不一样,栈要顶是最小的 ,底依次增大

队列 front 要最小,后面依次增大

9.25

自己照着书步骤来就行

9.26

struct position{int row;int col;
};
position *path ;//路线数组
int pathLength;
int **grid;//矩阵
int size;
position start,finish;
void showGrid();
void welcome(){cout<<"     -----------------"<<endl;cout<<"     欢迎来到电路布线问题"<<endl;cout<<endl<<endl<<"     按任意键开始输入"<<"- -"<<endl;getchar();
}void inputgrid(){//输入要链接的两点坐标,障碍,网格大小cout<<"enter grid size"<<endl;int i,j;cin>>size;if(size<1)//cout<<"error"<<endl;grid = new int*[size+2]; //多申请2维 ,最外一圈栅栏for(int i=0;i<=size+1;i++){grid[i]= new int[size+2];}for(int i=0;i<=size+1;i++)for(int j=0;j<=size+1;j++)grid[i][j]=0;for(int i=0;i<=size+1;i++){//围栅栏grid[0][i]=grid[size+1][i]=1;grid[i][0]= grid[i][size+1]=1;}cout<<"enter Roadblock"<<endl;cin>>i>>j;while(i!=-1){if(i>size+1||i<1||j>size+1||j<1){cout<<"Cross the border ,re enter"<<endl;cin>>i>>j;continue;}grid[i][j]=1;cin>>i>>j;}showGrid();cout<<"enter Roadblock"<<endl;cout<<"enter Starting point(row,col)"<<endl;cin>>start.row>>start.col;if(start.row>size+1||start.row<1||start.col>size+1||start.col<1||grid[start.row][start.col]==1){cout<<"Cross the border||Have obstacles"<<endl;exit(1);}cout<<"enter finish point(row,col)"<<endl;cin>>finish.row>>finish.col;if(finish.row>size+1||finish.row<1||finish.col>size+1||finish.col<1||grid[finish.row][finish.col]==1){cout<<"Cross the border||Have obstacles "<<endl;exit(1);}cout<<"OK"<<endl;}bool findPath(){if((start.col==finish.col)&&(start.row==finish.row)){//如果是一个点path=NULL;return true;}//arrayQueqe<position> q;position nbr;position here=start;grid[start.row][start.col]=2; //-2  为距离int numOfNbers=4;//4个相邻 四种选择//position offset[4];offset[0].row=0;offset[0].col=1;offset[1].row=1;offset[1].col=0;offset[2].row=0;offset[2].col=-1;offset[3].row=-1;offset[3].col=0;do{for(int i=0;i<numOfNbers;i++){nbr.row=here.row+offset[i].row;nbr.col=here.col+offset[i].col;if(grid[nbr.row][nbr.col]==0){//没有遍历到 没有标记grid[nbr.row][nbr.col]= grid[here.row][here.col]+1;if(nbr.col==finish.col&& nbr.row==finish.row)break;q.push(nbr);}}//for 循环完成已经把周围可走格子压入了q队列if(nbr.col==finish.col&& nbr.row==finish.row)break;//为什么要重复呢if(q.empty())return false;here=q.Front();q.pop();}while(1);pathLength= grid[finish.row][finish.col]-2;path= new position[pathLength];//回溯here=finish;for(int j=pathLength-1;j>=0;j--){path[j]=here;for(int i=0;i<numOfNbers;i++){nbr.row=here.row+offset[i].row;nbr.col=here.col+offset[i].col;if(grid[nbr.row][nbr.col]==j+2)break;}here= nbr;//回溯记录上一个位置 给这一轮的j--}return true;}
void showGrid(){for(int i=0;i<=size+1;i++){for(int j=0;j<=size+1;j++)cout<<grid[i][j]<<' ';cout<<endl;}
}void outputPath(){for(int i=0;i<pathLength;i++){cout<<path[i].row<<' '<<path[i].col<<endl;}cout<<"output END"<<endl;
}
int main(){welcome();inputgrid();if(findPath()){showGrid();outputPath();}elsecout<<"no path"<<endl;return 0;
}

9.27

void CleanMark(){int numOfNbers=4;//4个相邻 四种选择arrayQueqe<position> q;//position offset[4];offset[0].row=0;offset[0].col=1;offset[1].row=1;offset[1].col=0;offset[2].row=0;offset[2].col=-1;offset[3].row=-1;offset[3].col=0;here=start;grid[start.row][start.col]=0;do{for(int i=0;i<numOfNbers;i++){nbr.row=here.row+offset[i].row;nbr.col=here.col+offset[i].col;if(grid[nbr.row][nbr.col]>1){//标记了 但不走的路grid[nbr.row][nbr.col]= 0;if(nbr.col==finish.col&& nbr.row==finish.row)break;q.push(nbr);}}//for 循环完成已经把周围可走格子压入了q队列if(nbr.col==finish.col&& nbr.row==finish.row)break;if(q.empty())here=q.Front();q.pop();}while(1);for(int i=0;i<pathLength;i++){//上一个路线设置为1grid[path[i].row][path[i].col]=1;}cout<<"clean Finish"<<endl;outputPath();
}

9.28

设计模式和上题差不多 ,书上也有,不写了

另外怎么输出不同的体颜色呢?

9.29

感觉一样的,目的都是遍历使周围元素,时间复杂度也一样

9.30(括号匹配

不行,括号顺序不匹配了

9.31(管角

不行,因为顺时针遍历管角,满足则弹出一对(上一个遍历到但未匹配的),用队列就不是弹出一队了

9.32(离线等价类

可以 ,因为等价元素集合都一样,从哪开始寻找有关联(等价)都行

9.33

可以,没有顺序要求

9.34

思路:

1. 结构job也设置一个 changeTime,也有转换状态,每个工序之间也要等待时间

2.机器执行队列,执行前要检查是否工序处于转换状态,若处于则弹出调度到队尾(只有此工序则一直等待)---> (nowTime== arrivalTime+changeTime||第一道工序)&&机器不处于转换状态 才能执行此任务工序

3. 函数 changeState同时可以改变工序状态,若机器转换>工序转换时间 ,则只要改变机器状态(工序自然而然能执行),反之亦然

9.35

就不是离线了

设置一个全局变量Maxtime 为仿真截止时间 ,在运行的任务算未完成的

第九章总结

本章主要讲了队列及其相关应用

方式

a 分为数组和链式储存,总体来看数组效率较高

数组可以用不同的映射方式,比如循环数组 ,基本方法时间控制在O(1)

应用

列车重排

电路布线(最短路径):李式路由算法

分为距离标记 和 回溯路径标记两个部分

距离标记用队列(或栈)寻找可行的路,并标记距离(+1),循环添加至队列直到到                         达目标

图元识别:感觉有点像寻找等价类的情况,一个颜色相当于一个等价类,循环寻找

工厂仿真:本章最复杂的问题

分为3个结构和一个类 task job machine eventList

每一个右相互关联,有.难度

  第十章

10.1

自己看

10.2

电话簿,购票系统,搜索记录

查找操作都需要

10.3

任务表单的存取?

10.4

C++ 中的 hash_map, unordered_map_小肥羊快快跑-CSDN博客

10.5

注意: 1 结构体也要缺省构造函数

2 class 普通方法要加public ,不然访问不了

#include<iostream>
using namespace std;
template<class K,class E>
struct pairNode{//数对结构K KEY;E Element;pairNode (){}pairNode(pairNode& theNode){KEY=theNode.KEY;Element=theNode.elemeny;}pairNode(K theKEY,E theElement){KEY=theKEY;Element=theElement;}
};template<class K,class E>
class dictionary{public:virtual ~dictionary(){}virtual bool empty() const=0;virtual int size() const=0;//返回字典中数对的个数virtual pairNode< K,E >* find(K&) const =0;//返回匹配数对的指针 ,若无返回NULLvirtual void erase(const K&) =0;//删除匹配数对virtual void insert( pairNode< K,E>& ) =0;//如果相同关键字则替换 ,无则插入
};template<class K,class E>
class sortedArrayList:public dictionary< K,E>{//顺序(关键字)数组方式public:sortedArrayList(int init=10);~sortedArrayList(){delete [] array;}bool empty()const{ return ListSize==0;}int size()const {return ListSize;}pairNode< K,E >* find( K&) const;void erase(const K&);void insert(pairNode<K,E>& );private:int ListSize;pairNode<K,E> *array;};
template<class K,class E>
sortedArrayList<K,E>::sortedArrayList(int init){array= new pairNode<K,E> [init];ListSize =0;
}
template<class K,class E>
pairNode< K,E >*
sortedArrayList<K,E>::find( K&theKEY) const{for(int i=0;i<ListSize;i++){if(theKEY== array[i].KEY)return array+i;}return NULL;
}
template<class K,class E>
void
sortedArrayList<K,E>::erase(const K& theKEY){int i;for( i=0;i<ListSize;i++){if(theKEY== array[i].KEY){copy(array+i+1,array+ListSize,array+i);break;}}if(i==ListSize)cout<<"no find theKEY"<<endl;elsecout<<"erase OK"<<endl;
}
template<class K,class E>
void
sortedArrayList<K,E>::insert( pairNode<K,E>& theNode){int i;for(i=0;i<ListSize;i++){if(theNode.KEY<=array[i].KEY)break;}if(theNode.KEY==array[i].KEY)array[i].Element=theNode.Element;else if(i==ListSize){array[i].Element=theNode.Element;array[i].KEY=theNode.KEY;}else {copy(array+i,array+ListSize,array+i+1);array[i].Element=theNode.Element;array[i].KEY=theNode.KEY;}ListSize++;cout<<array[ListSize-1].Element<<endl;}int main(){sortedArrayList<int,int> a;cout<<a.empty()<<endl;pairNode<int ,int> node(5,666);a.insert(node);
}

10.6

尾巴节点储存要操作的关键字

这样判断时,当theKey== current(尾部)->key 时就已经遍历结束

或者插入到最后时,直接尾部当插入的节点,尾指针指向新创建的节点

删除时,尾指针前移

10.7

template<class K,class K>int skipList<K,E>::level(float p) const{int temp= rand();//p为概率float Rmax=RAND_MAX*p;//初始值为 1到 1/pint lev=0;while (temp>Rmax){lev++;Rmax+= Rmax*p;}return (lev<= maxLeve)? lev:maxLevel;}

10.8

方法细节改一下

如:删除 ,找到目标值最边最右的值 跳出循环,然后开始向右遍历依次删除直到不相等

插入,相等时,不改变值,而是插入到相当序列中最后面

10.9

从0级开始删(必包含),向上遍历,利用next 和last 数组 ,删除各级别

时间复杂度O(maxLevel)

跳表总结:

a: 0-MAX级表

0级表就是初始链表,包含所有数对

i级链表每(p^-1)^i个元素取一个,其中p是i-1级与i级 数对个数的比值

i级链表有 N* p^i个 数对

MAX一般为 【log(p^-1) N】 其中N为总对数

b: 属于i级的数对,必属于0至(i-1) 的数对集合 --> i级是从i-1 级数对中取的

10.10

设置maxKey个桶就行了 ,每个桶最多容纳一个

10.11

#include<iostream>
#include<string>
using namespace std;
long threeToLong(string s){if(s.length()!=3)cout<<"error!"<<endl;long result = s.at(0);result = (result<<8)+s.at(1);return (result<<8)+s.at(2);
}int main(){string s("wcd"),s1("wca");cout<<threeToLong(s)<<endl;cout<<threeToLong(s1)<<endl;return 0;
}

10.12

要点是long四个字节 ,每个字符储存在一个字节内,通过与0 为0 加位移 来取出数据

string
LongToString(long answer){string s;long temp;temp=(answer&0xFF0000)>>16;s.push_back(temp);temp=(answer&0x00ff00)>>8;s.push_back(temp);temp=(answer&0x0000ff);s.push_back(temp);return s;
}

10.13

一般要求桶内元素为【r/b】 向上整取,和向下整取 才为均匀散列表

1)

不是 最后几个桶永远为0,不均匀

2)     不是 大部分落入偶数桶中 p249面原因

3)      不是 ,大部分奇数桶中,同理

4)      不是,桶太多了

10.14

一般要求取大于20的素数

1,2 是 都是大与20的素数

10.15

单纯的加起来就行了,不用移位

10.16

#include <iostream>
#include<math.h>
using namespace std;bool isPrime( int num )
{int tmp =sqrt( num);for(int i= 2;i <=tmp; i++)if(num %i== 0)return 0;return 1;}
int
ToD(float a ){if(a<20)return 21;int result=(int)a;while(1){if(isPrime(result) )return result;result++;}}int main(){cout<<ToD(21.32)<<endl;return 0;
}

10.17

装载因子 10/13   -->  r/b

成功时 3.17次

失败时 9.89次

注意: 书上好像说反了 U是不成功的查找次数,S是成功时的平均查找次数 

差别可能是数对的问题

10.18-10.20

算装载因子套公示就行了

10.21

1)

接下去真不会了,数学不行

2)

不行,因为跟开始遍历的位置(表头)不会发生变化

10.22

#include<iostream>
using namespace std;
float
Linear_detection_Un(float a){return (1+1/ ((1-a)*(1-a)))/2;  //10-3公示
}
float
Linear_detection_Sn(float a){return (1+1/(1-a))/2;  //10-4
}
float
Random_detection_Sn(float a){return 1+a/2; //   1+a/2
}
int main(){cout<<"Linear_Un/Sn:"<<"------"<<"Random_Sn"<<endl;for(int i=1;i<=9;i++)  {cout<<Linear_detection_Un((float)i/10)<<"  ";cout<<Linear_detection_Sn((float)i/10)<<"   ";cout<<Random_detection_Sn((float)i/10)<<endl;}// 链式散列表的随机探查 ,桶可以不止有一个数对 // 当a>1 时 Un= a*(a+3)/2(a+1)  // 小于1时, 平均搜索不可能大于每个桶的平均长度 Un<= a}

10.23

#include<iostream>
#include<math.h>
using namespace std;
int
fun(float Sn,float n){return  n/(1-1/(2*Sn-1));//反解D
}
int
fun1(float Un,float n){return  n/(1-sqrt(1/(2*Un-1)) );
}int main(){cout<<fun(3,50)<<"    ";cout<<fun1(20,50)<<endl;cout<<fun(5,500)<<"    ";cout<<fun1(60,500)<<endl;cout<<fun(2,10)<<"    ";cout<<fun1(10,10)<<endl;}

10.24

【0,MaxElements】 个元素

那我就取MaxElements个桶呗,或者均匀散列表要求

10.25

错的,调

template<class K,class E>
void
hashTable<K,E>::changeTable(){//copypair<K,E>** temp =  new pair<K,E> *[divisor*2+1];for(int i=0;i<divisor*2+1;i++)temp[i]=NULL;copy(table,table+dSize,temp);int S=divisor;divisor= divisor*2+1;delete table;table = temp;///for(int a=0;a<S;a++){if(table[a]!=NULL){int original = table[a]->first%divisor;if(original!=a){if(table[original]==NULL){//如果原始桶为空则放入,table[original]= table[a];table[a]==NULL;     }else  { int j=1;while(table[(original+j)%divisor]!=NULL)j++;table[(original+j)%divisor]=table[a];table[a]=NULL;}            }  }          }
}

10.26

最坏O(divisor)

template<class K,class E>
void
hashTable<K,E>::erase(const K& theKey){//删除一个后 把不在自己原始桶的都向前移,int a=search(theKey);cout<<a<<endl;int pre=a,S=a; //记录上一个位置table[a++]= NULL ;for(;a%divisor!=S;a++){//从删除的后面循环遍历if( table[a%divisor]!=NULL){int original = table[a%divisor]->first%divisor;if(original!=a){if(table[original]==NULL)//如果原始桶为空则放入,table[original]= table[a%divisor];        else              table[pre]=table[a%divisor];table[a%divisor]=NULL;pre=a%divisor;} }           }
}
template<class K,class E>
void
hashTable<K,E>::show(){int i;for(i=0;i<divisor;i++)if(table[i]!=NULL)cout<<i<<"----"<<table[i]->first<<endl;
}
int main(){hashTable<int,int> a(6,1);pair<int,int> s(2,100),s1(4,101),s3(8,102),s4(11,103),s5(12,104),c(18,111);a.insert(s);a.insert(s1);a.insert(s3);a.insert(s4);a.insert(s5);a.erase(2);a.erase(11);a.insert(c);a.erase(12);a.show(); return 0;}

10.27

相当于设置一个标志位 false为有数对,true 为空

不是通过检查是否为NULL 或等于本身来判断情况

10.28

就是向前向后探测,利用平方

散列表(四)冲突处理的方法之开地址法: 二次探测再散列的实现 - AlanTu - 博客园 (cnblogs.com)

10.29

冲突时,用另一个散列函数来寻找位置

Hash算法:双重散列 - 賣贾笔的小男孩 - 博客园 (cnblogs.com)

10.30

线性探测:要判断每一个元素是否为空,冲突时还要线性寻找

链式:  要遍历同一个桶的所有元素,且不能用下标来代替指针

10.31-32

自己套公式

10.33

上一章好像写过?

搜索时==表尾的自身值时表示搜索失败 ,不用与NULL比较

10.34

不就是基本链表操作吗,类似于邻接表,找到邻边,插入到右表

10.35-10.36

思路一样

尾结点共用一个 ,都指向这个就行了 ,同一个方法同一时间只能执行一个

10.37

1) 肯定不行啊,要指向不同个桶 就得要不同个头结点

2)没必要,又不是循环链表,遍历不到头结点去

3)思路一致

4) 头结点:避免特殊情况(插入在第一个,邻表要改)

尾结点:避免NULL的判断

推荐都不使用,就是纯粹,性能其实跟这些无伤大雅,检验NULL和检验

是否为尾值不是一样吗(插入到表尾除外

10.38

STL之list容器详解 - Sam大叔 - 博客园 (cnblogs.com)

list就是一个双向链表

链表的元素是一个链表

10.39

不用copy,先增加领边表,然后从第一个领边开始遍历域表,

不属于自己原始桶的移动到原始桶,思路和数组的一致

10.40

散列表的性能分析 - 计算机的探索者 - 博客园 (cnblogs.com)

肯定是开放定址法效率高一点 ,推荐使用STL hash_map,肯定比自己写效率高

10.41

a=n/b -->平均长度

无序,插入到右端,--> 遍历到底: 只有一种可能的范围使其失败

Un = 1/(i+1)*(i+i^2) = i=a;

Sn = 1+a/2

(与书p257一致),计算到表头的平均长度

10.42

10.43

0123

1到13的累加=91 乘9个 -->

-->0+1+...+12+8

10.44

主要体现在查找和插入方面上

应该链表好一点,查找次数少

10.45

完全有可能,不重复的字符越多,字典数目就越大,且转换不成压缩码

10.46

可能

10.47

重新散列?可以减少查找的时间,当字典越长时,所需时间越多

自行实验

10.48

1) list选用arrayList

索引表选用链表,或Hash_table

2) 思路跟本章开头差不多 ,相当于Key是string类型

第十章总结

hash_table(总

#include<iostream>
using namespace std;
// pair 自带的容器
template<class K,class E>
class hashTable {public:hashTable(int theDiv=13,float theMaxFactor=0.8){divisor=theDiv;MaxFactor=theMaxFactor;dSize=0;table= new pair<K,E>* [divisor];for(int i=0;i<divisor;i++)table[i]= NULL;     }int search(const K& theKey) const;pair<K,E>* find(const K& theKey) const;void insert(const pair<K,E>& thePair);int hash(const K& theKey);//用此函数代替 void changeTable();//2*size+1 超过定义因子void erase(const K& theKey);void show();private:pair<K,E>** table;int dSize;int divisor;//也是默认桶的数量float MaxFactor;//用户指定//hash<K> hash;
};
template<class K,class E>
int
hashTable<K,E>::hash(const K& theKey){//默认就是整形 直接返回 return theKey;
}
template<class K,class E>
int
hashTable<K,E>::search(const K& theKey) const{int i= theKey%divisor;int j=i;do{if(table[j]==NULL ||  table[j]->first== theKey)return j;j=(j+1)%divisor;}while(j!=i);return j;
}
template<class K,class E>
std::pair<K,E>* //要加命名空间
hashTable<K,E>::find(const K& theKey) const{int b=search(theKey);if(table[b]==NULL || table[b]->first != theKey)return NULL;return table[b];
}template<class K,class E>
void
hashTable<K,E>::insert(const std::pair<K,E>& thePair){int b=search(thePair.first);if(table[b]==NULL) {table[b] = new pair<K,E>(thePair);dSize++;}else {if( table[b]->first == thePair.first)table[b]->second= thePair.second;else {cout<<"FULL!"<<endl;exit(1);}}float a=(float)dSize/(float)divisor;if(a>MaxFactor)changeTable();}
template<class K,class E>
void
hashTable<K,E>::changeTable(){//copypair<K,E>** temp =  new pair<K,E> *[divisor*2+1];for(int i=0;i<divisor*2+1;i++)temp[i]=NULL;copy(table,table+dSize,temp);int S=divisor;divisor= divisor*2+1;delete table;table = temp;///for(int a=0;a<S;a++){if(table[a]!=NULL){int original = table[a]->first%divisor;if(original!=a){if(table[original]==NULL){//如果原始桶为空则放入,table[original]= table[a];table[a]==NULL;     }else  { int j=1;while(table[(original+j)%divisor]!=NULL)j++;table[(original+j)%divisor]=table[a];table[a]=NULL;}            }  }          }
}
template<class K,class E>
void
hashTable<K,E>::erase(const K& theKey){//删除一个后 把不在自己原始桶的都向前移,int a=search(theKey);cout<<a<<endl;int pre=a,S=a; //记录上一个位置table[a++]= NULL ;for(;a%divisor!=S;a++){//从删除的后面循环遍历if( table[a%divisor]!=NULL){int original = table[a%divisor]->first%divisor;if(original!=a){if(table[original]==NULL)//如果原始桶为空则放入,table[original]= table[a%divisor];        else              table[pre]=table[a%divisor];table[a%divisor]=NULL;pre=a%divisor;} }           }
}
template<class K,class E>
void
hashTable<K,E>::show(){int i;for(i=0;i<divisor;i++)if(table[i]!=NULL)cout<<i<<"----"<<table[i]->first<<endl;
}
int main(){hashTable<int,int> a(6,1);a.show(); return 0;}

本章主要讲了 数对 的储存方法

--> 字典

主要是hash表 ,用映射方式储存在空间中,大大减少方法时间 {

a. 映射函数 ,可以把任意类型的Key转换为整型值 以此来储存在表中

如string通过移位等转换为整型

b. 当冲突时,可以选择方法来避免冲突,如线性探测,双向探测,再散列等

c.常用的散列有除余法,应选择不小于20的素数

d.性能分析,有一套完整的公示 见10.17

e.链式hash表类似于邻接表

}

跳表 见10.9

还讲了LZW的压缩应用{10.42

利用前缀+c 制成压缩字典 ,储存在hash表中

解压时将前缀代码复原成原始子串,形成解压字典

}

   第十一章

数据结构第十一章(二叉树及其他树)自练答案_万千只cnm&的博客-CSDN博客

第十二章

第十二章 优先队列_万千只cnm&的博客-CSDN博客

第十三章

第十三章 赢/输者树(选择树,决策树_万千只cnm&的博客-CSDN博客

第十四章

第十四章 搜索树_万千只cnm&的博客-CSDN博客

第十五章

第十五章 平衡搜索树(AVL 红黑 分裂 m插搜索树/ B+树_万千只cnm&的博客-CSDN博客

第十六章 图

第十六章 图_万千只cnm&的博客-CSDN博客

第十七章 贪婪算法

第十七章 贪婪算法_万千只cnm&的博客-CSDN博客

第十八章  分而治之

第十八章 分而治之(归并排序)_万千只cnm&的博客-CSDN博客

第十九章 动态规划

第十九章 动态规划(背包/矩阵链/顶点路径_万千只cnm&的博客-CSDN博客

第二十章 回溯法

第二十章 回溯法_万千只cnm&的博客-CSDN博客

第二十一章 分支定界

第二十一章 分支定界_万千只cnm&的博客-CSDN博客

总总结

终于看完了,后面几章有难度,如果想真正懂,还是得刷题

下一步准备学 linux 和html css JavaScript 和py 共勉

附:

五大常用算法:分治、动态规划、贪心、回溯和分支界定 - 小山药 - 博客园

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

  1. [最新答案V0.4版]微软等数据结构+算法面试100题[第41-60题答案]

    [最新答案V0.4版]微软等数据结构+算法面试100题[第41-60题答案] 作者 July.Csdn网友 二零一一年一月四日 ------------------------------------ ...

  2. [整理III]微软等数据结构+算法面试100题[最新第61-80题]

    精选微软等数据结构+算法面试100题[第61-80题] --最新整理公布 昨日,11.19,最新整理了,第61-80题,现在公布. 可以这么说,绝大部分的面试题,都是这100道题系列的翻版, 此微软等 ...

  3. 横空出世,席卷Csdn [评微软等公司数据结构+算法面试100题]

    横空出世,席卷Csdn ---评微软数据结构+算法面试100题 作者:July 时间:2010年10月-11月.版权所有,侵权必究. --------------------------------- ...

  4. python中栈的描述是_数据结构与算法:Python语言描述 栈和队列.ppt

    数据结构与算法:Python语言描述 栈和队列 迷宫问题 迷宫问题的特点: 存在一集可能位置,一些位置相互连通,一步可达 一个位置可能连通若干位置,出现向前探查的多种可能(有分支) 目标是找到一条路径 ...

  5. 7.使用php描述冒泡排序,PHP 数据结构 算法描述 冒泡排序 bubble sort

    PHP 数据结构 算法描述 冒泡排序 bubble sort 复制代码 代码如下: /** * 冒泡排序 bubble sort * * 原理:多次循环进行比较,每次比较时将最大数移动到最上面.每次循 ...

  6. 资料分享:送你一本《数据结构与算法:Python语言描述》电子书!

    下图为 TIOBE 3月编程语言排行榜. 从榜单来看,曾经铁打的 Java.C.C++ 局势,早已在数月前被 Python 的闯入而打破.究其根由,并非是 C++ 的应用领域正在逐渐缩减,而是随着人工 ...

  7. 《数据结构与算法:Python语言描述》一1.3算法和算法分析

    本节书摘来自华章出版社<数据结构与算法:Python语言描述>一书中的第1章,第1.3节,作者 裘宗燕,更多章节内容可以访问云栖社区"华章计算机"公众号查看 1.3算法 ...

  8. python思想读后感_数据结构与算法:Python语言描述读后感1000字

    <数据结构与算法:Python语言描述>是一本由裘宗燕著作,机械工业出版社出版的平装图书,本书定价:CNY 45.00,页数:343,特精心从网络上整理的一些读者的读后感,希望对大家能有帮 ...

  9. 【Java数据结构及算法实战】系列002:算法的四种描述方式

    本节是<Java数据结构及算法实战>系列的第2节,主要介绍描述算法的常用的4种方式. 要定义一个算法,我们可以用自然语言.流程图.伪代码的方式描述解决某个问题的过程或是编写一段程序来实现这 ...

最新文章

  1. 经典算法题每日演练——第六题 协同推荐SlopeOne 算法
  2. matlab里点云的读入显示和保存
  3. ArcGIS Server 部署与配置
  4. python gui插件_Python进阶量化交易专栏场外篇17- GUI控件在回测工具上的添加
  5. java编程连接mysql_Java编程学习之JDBC连接MySQL
  6. 蔡司三坐标_蔡司三坐标测针的安装指南
  7. Qt|OpenGL-天空盒子的创建
  8. 抖音升级老年人防沉迷提醒机制 覆盖多个使用场景
  9. Linux故障自愈脚本,实现故障自愈要攻克的3个问题以及开箱即用的方案
  10. 列表、元组、字典、集合的定义与操作
  11. 1450. Russian Pipelines(spfa)
  12. apache sentry
  13. uos系统安装教程_统一操作系统UOS下载&安装图文教程:尝鲜记(一)
  14. ivms4200 远程桌面访问测试过程及问题汇总
  15. 40家重污染行业上市公司进“黑名单”
  16. html5的canvas绘制迷宫地图
  17. containsString和rangeOfString
  18. Gartner首次发布中国超融合市场竞争格局报告,ZETTAKIT泽塔云的差异化优势成重点关注对象
  19. 鸿蒙电脑系统运行exe,鸿蒙传说电脑版_电脑版鸿蒙传说下载「含模拟器」-华军软件园...
  20. 不念过往,不畏将来——告别曾经

热门文章

  1. POJ 1061 青蛙的约会
  2. 博客园背景滴墨水特效
  3. 2018第九届蓝桥杯JavaA组省赛真题详解
  4. 机器学习---sklearn
  5. 最全zabbix安装部署
  6. BZOJ.4598.[SDOI2016]模式字符串(点分治 Hash)
  7. 【机器学习基础】三层神经网络
  8. 第六期 自定义IP添加-PWM 基于ARTY A7的MicroBlaze系统搭建与应用
  9. 【Proteus仿真】BCD码转十进制(74HC42)
  10. SRAM FPGA控制,实际产品拷机测试过