瑞士著名的科学家N.Wirth 教授曾提出:数据结构+算法=程序。
数据结构是程序的骨架,算法是程序的灵魂
前言:虽然我找到了Android 实习生的职位,但是觉得自己实习生难以在北京那个高消费的地方生存,所以找了一个少儿编程讲师的兼职,主讲C++,面试的时候,居然听说要求有211、985考研的算法题的难度,当时我就惊了,现在小孩子太不容易了,自己也太low了。我也就大二的时候研究够一阵子,如今很多东西都已经忘了,数据结构也没剩多少了,而且目前所有的公司,都需要算法,所以决定回炉重造。
指针的使用,指针与数组
比如二级指针不能直接指向二维数组,但是可以通过下面方式实现:定义指针数组指向二维数组,二级指针指向指针数组
数组与指针数组比较
数组指针 vs 指针数组 (b[3][4])
|
指针数组 |
数组指针 |
定义方式 |
int *pb[3] |
int (*p)[4] |
数据类型本质 |
数组: 数组的元素为指针 |
指针: 指针指向的数据类型为数组 |
赋值 |
pb[i] = b[i] |
p=b |
数组元素访问 |
pb[i][j] *(pb[i] + j) (*(pb+i))[j] *(*(pb+i)+j) |
p[i][j] *(p[i] + j) (*(p+i))[j] *(*(p+i)+j)
|
数组与指针数组比较
本质是函数调用时实参给形参赋值。指针与数组相关的实参与形参对应关系
实参(int) |
形参 |
||
a[3] |
int *p |
或 |
int p[] |
a[3][4] |
int (*p)[4] |
或 |
int p[][4] |
*a[3] |
int **p |
或 |
int *p[] |
算法具有的特性:
- 有穷性:算法是由若干条指令组成的有穷序列,总是在执行若干次后结束,不可 能永不停止。
- 确定性:每条语句有确定的含义,无歧义。
- 可行性:算法在当前环境条件下可以通过有限次运算实现。
- 输入输出:有零个或多个输入,一个或多个输出。
时间复杂度:算法运行需要的时间,一般将算法的执行次数作为时间复杂度的度量标准。
空间复杂度:算法占用的空间大小。一般将算法的辅助空间作为衡量空间复杂度的标准。空间复杂度的本意是指算法在运行过程中占用了多少存储空间。算法占用的存储空间
- 输入/输出数据;
- 算法本身;
- 额外需要的辅助空间。
从C到C++
“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想,把系统看成一个过程的集合体,分析出解决问题所需要的步骤。
“面向对象”(Object Oriented)是一种以对象为中心的编程思想,把系统看成一个相互作用的对象集,对象之间通过发送和响应消息进行交互。
对象即现实世界中客观存在的事物,面向过程的编程方式是将问题分解为过程,而面向对象的编程方式以问题中的对象为中心思考问题。
C++中的对象是将数据和对数据的操作封装在一起的实体,即一种抽象数据类型——“类”类型的实体。
类:与int、char相似,是一种数据类型。类的构成包括数据成员和成员函数:数据成员对应类的属性;成员函数对应类的方法,用于操作类的属性。
class 类名
{
数据成员
...
成员函数
...
};
class Student
{
private:
char name[20];
char id[15];
int age;
public:
void show()
{
…
}
};
- 1)对象的属性:用数据集合描述对象的状态
- 2)对象的方法:用函数来实现对象的行为
- 3)对象之间通过消息通信,实现动态联系
从C到C++的过渡
C语言的输入输出由库函数实现,主要包括:scanf(), printf(), getc(), gets(), putc(), puts()等,它们包含在文件stdio.h中。
C++语言的输入输出利用运算符>>和<< ,以及cin和cout,,它们包含在文件iostream.h中
# include <iostream.h>
int main(void)
{
double a, b, c;
cout<<“Input two float numbers:”; // 插入符
cin >> a >> b; // 提取符,用空格或回车间隔
c=a+b;
cout<<“a+b=”<<c<<endl; // endl表示输出一个换行符,等同于转义字符’\n’
return 0;
}
几点说明:
- C++中没有专门的输入/输出语句,可以利用输入流和输出流来进行数据的输入和输出,此时,程序开头要包含头文件iostream.h;
- 运算符“>>”称为提取运算符,表示将暂停程序的执行,等待用户从键盘上输入相应的数据。一个提取运算符只能跟一个变量名;
- cin输入流的一般语法格式:
cin>> <变量名1>[>> <变量名2> >> … >> <变量名n>];
- 运算符“<<”称为插入运算符,它将紧跟其后的表达式的值输出到显示器当前光标的位置,也可以输出转义字符;
- cout输入流的一般语法格式:
cout<< <表达式1>《<< <表达式2> << … << <表达式n>》;
引用的基本概念
在一个程序中用不同的变量名指向同一地址的同一内容的数据类型描述称为引用。
引用的一般格式为:
<类型名> &引用型函数名或变量名 = 前已声明的(常)变量名
int num =50;
int &ref =num;
ref是对num的引用,即ref是num的别名,它们共用一个存储空间,对ref的任何操作等同于对num的任何操作。
几点说明:
1、引用的目标变量类型要与引用变量的类型一致,即ref的类型为int &,num的类型为int。
2、指针和引用的区别
①指针变量存储空间中保存了目标变量存储空间的地址值,而引用不分配空间,引用必须初始化。
②指针可以修改它的指向,但引用和对象绑定后,将无法修改
引用参数
引用的真正目的就是在不同的作用域中分别使用引用名和被引用的目标变量名,比如:调用函数和被调用函数。
例1:SwapInt()函数利用指针参数来实现互换它的两个参数
#include <iostream.h>
void SwapInt( int *a ,int *b)
{
int temp;
temp = *a;
*a = *b ;
*b =temp ;
}
void main( )
{
int num1 , num2 ;
num1 =5 ,num2 =10 ;
SwapInt( &num1 ,&num2 );
cout<< “num1=”<<num1<< “,num2=”<<num2<<endl ;
return 0;
}
运行情况如下:num1= 10, num2 = 5
例2:SwapInt()函数利用指针参数来实现互换它的两个参数
#include <iostream.h>
void SwapInt( int &a ,int &b)
{
int temp;
temp = a;
a = b ;
b =temp ;
}
int main(void)
{
int num1=5, num2=10;
SwapInt( num1, num2 );
cout<< “num1=”<<num1<< “,num2=”<<num2<<endl ;
return 0;
}
在整个SwapInt函数执行期间,对a的读写实际上是通过对main函数的num1变量的读写来完成的。
传引用与传指针相比,在SwapInt函数内,无法修改a和b的绑定目标,而这一点在指针传递机制中往往需要程序员严格把关。由于引用和目标的固定绑定关系,引用常被看做是安全的指针。
有时,既为了使形参共享实参的存储空间,又不希望通过形参改变实参的值,则应当把该形参说明为常量引用,例如:
void fun(const int &cra);
函数重载
C中规定,每个函数都必须有唯一的名字,不允许有重名的函数。这样就带来很多不便。如C运行库中的求绝对值函数abs(), labs(), fabs()。尽管它们处理的几乎是完全相同的工作,但在C中却要用三个不同的函数名来区分。
在C++中,函数可以共享同一个名字,只要这些同名函数的参数表有所区别,这就是函数重载的概念。同一作用域内名字相同,但参数不同的函数称为重载函数。
#include <iostream.h>
//abs( )函数按三种形式重载
int abs ( int i);
long abs(long l);
double abs(double d);
int main(void)
{
cout<<abs(-10)<<endl ;
cout<<abs(-9L)<<endl;
cout<<abs(-11.5)<<endl;
return 0;
}
int abs(int i)
{ return i<0?-i :i ; }
long abs (long l)
{ return l<0?-l:l ; }
double abs(double d)
{ return d<0 ? –d :d ; }
运行情况如下:
10
9
11.5
重载函数的参数差别:
参数类型、参数个数、参数类型的次序。
内联函数
C语言中,可以用#define来进行常量宏,也可以定义带参数表达式的宏。预处理器会在编译之前把宏名展开成相应的字符串或表达式。
#include <iostream.h>
#define max(x,y) ((x)>(y) ? (x) :(y)) // 定义宏max(x ,y) 为x和y中的较大者
int main( )
{
int a ,b ,c ,t ;
a=1 ,b=2 ,c =3 ;
t = max( a+b , c ) ; // 编译预处理器对表达式进行宏展开:t =(( a+b )>( c ) ?( a+b ): (c) );
return 0;
}
在C++中,可以利用内联函数达到类似的效果。内联函数用关键字inline。和带参数的宏定义相比,内联函数的形式更像普通函数,可读性强,因此,建议在C++中使用内联函数代替带参数的宏定义。
#include <iostream.h>
inline int max(int a ,int b)
{
return a>b?a:b ;
}
int main( )
{
int t ;
t = max(10, 20 ); // 被max相应的函数体所替换(代码扩展):t =10>20?10:20;
cout<<t<<endl ;
return 0;
}
小结:
- C++是在C语言的基础上发展而来的。对C语言是完全兼容的。在C语言的基础上,增加了新的语言成分和抽象数据类型的概念,就 得到了C++。
- 并不需要在知道C++的所有细节之后才能写出好的C++程序,请特别关注程序设计技术,而不是各种语言特征。
- 学习C++,必须要有C语言的基础。记住:C++没有高手,C语言才有高手。
- 面向对象程序设计的重点是类的设计,而不是对象的设计。