C语言编程预备知识
-
CPU 内存条 硬盘 显卡 主板 显示器 之间的关系
CPU的中文名称是中央处理器,又可称中央处理单元、微处理器;它是计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元,其功能主要是解释计算机指令以及处理计算机软件中的数据。
显卡的主要作用是将CPU提供的指令和数据进行相应的处理变成显示器能够接受的文字或图象后显示出来,以便为用户继续运行或终止程序提供依据。
电脑主板是电脑内部最重要的组成部分之一,它起着连接和管理各种硬件设备的作用。
-
Hello World程序如何运行起来的
通过编译生成一个可执行的exe文件,操作系统调用CPU打开文件
-
什么是数据类型
基本类型数据
整数
整型 – int 4个字节
短整型 --short int 2个字节
长整型 – long int 8个字节
浮点数(实数)
单精度浮点数 – float 4个字节
双精度浮点数 – double 8个字节
字符
char --1个字节
复合类型数据
结构体
枚举
共用体
-
什么是变量
变量的本质就是内存中一段存储空间
-
CPU 内存条 VC++6.0 操作系统 之间的关系
-
变量为什么必须初始化
所谓初始化就是赋值的意思
-
如何定义变量
数据类型 变量名 = 要赋的值;
等价于
数据类型 数据名;
变量名 = 要赋的值;
举例子:
int i = 3; //等价于 int i;i = 3; int i,j;//等价于int i; int j; int i,j=3;//等价于int i; int j; j = 3; int i=3,j=5;//等价于int i; int j; i = 3;j = 5; int i,j;i = j = 5;//等价于int i;int j;i = 5;j = 5; /* 多行注释 */
-
什么是进制
十进制就是逢十进一(D) 0 1 2 3 4 5 6 7 8 9 10
二进制就是逢二进一(B) 0 1 10 11 100 101 110 111
八进制就是逢八进一(O) 0 1 2 3 4 5 6 7 10 11 1
十六进制就是逢十六进一(H) 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14
-
常量在C语言中是如何表示的
整数
十进制:传统的写法
十六机制:前面加0X或0x
八进制:前面加0 注意是数字不是字母o
浮点数
传统的写法
float x = 3.2;//传统
科学计数法
float x= 3.2e3;//x的值是3200
float x = 123,45e-2;//x的值是1。2345
字符
单个字符用单引号括起来
字符串用双引号括起来
-
常量以什么样的二进制代码存储在计算机中
编码的问题:整数是以补码的形式转化为二进制代码存储在计算机中的
实数是以IEEE754标准转化为二进制代码存储在计算机中的
字符的本质实际也是与整数的存储形式相同(通过ASCII码转成整数后存储)
11.代码规范化
代码的可读性更强【容易让自己和别人更清楚的看懂程序】
使程序更不容易出错
12.什么是字节
字节就是存储数据的单位,并且是硬件所能访问的最小单位
1字节=8位
1K=1024字节
1M=1024k
1G=1024M
1T=1024G
13.不同类型数据之间相互赋值的问题
暂不考虑
int i = 45;
long j = 102345;
i = j;
printf("%d %ld\n",i,j);
float x = 6.6;
double y = 8.8;
printf("%f %lf\n",x,y);
14.什么是ASCII
ASCII不是一个值,而是一个规定
ASCII规定了不同的字符是使用哪个整数值去表示
它规定了’A’–65 ‘B’–66 'a–87 ‘b’–98 ‘0’–48
15.字符的存储【字符本质上与整数存储的方式相同】
基本的输入和输出函数的用法
printf()–将变量的内容输出到显示器上
四种用法
1.printf(“字符串\n”);
2.printf(“输出控制符”,输出参数);
3.printf(“输出控制符1 输出控制符2。。。”,输出参数1,输出参数2,。。。。);
输出控制符和输出参数的个数必须一一对应
4.printf(“输出控制符 非输出控制符”,输出参数):
输出控制符包含如下:
%d–int %ld–long int %f–float %c–char %lf–double %x(%X %#X)–int或long int 或short int %o–同上 %s–字符串
为什么需要输出控制符
1.01组成的代码可以表示数据也可以表示指令
2.如果01组成的代码表示的是数据的话,那么同样的01代码组合以不同的输出 格式输出就会有不同的输出结果
scanf()【通过键盘将数据输入到变量中】
两种用法:
用法一:scanf(“输入控制符”,输入参数);
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中。
用法二:scanf(“非输入控制符 输入控制符”,输入参数);
功能:将从键盘输入的字符转化为输入控制符所规定格式的数据,然后存入以输入参数的值为地址的变量中。
非输入控制符必须原样输入
如何使用scanf编写出高质量代码
1.使用scanf之前最好先使用printf提示用户以什么样的方式来输入
2.scanf中尽量不要使用非输入控制符,尤其不要用\n
3.应该编写代码对用户的非法输入做适当的处理
char ch;
while((ch=getchar())!='\n')
continue;
运算符
算术运算符
+ - & /(除) %(取余数)
关系运算符
> >= < <= !=(不等于) ==(等于)
逻辑运算符
!(非) &&(并且;与) ||(或)
!真 假
!假 真
真&&真 真
真&&假 假
假&&真 假
假&&假 假
真||假 真
假||真 真
真||真 真
假||假 假
C语言对真假的处理
非零是真
零是假
真是1表示 假是0表示
&&的左边的表达式为假 右边的表达式肯定不会执行
例如:m=(1>2)&&(k=5);
||的左边的表达式为真 右边的表达式肯定不会执行
赋值运算符
= += *= /= -=
优先级别
算术 > 关系 > 逻辑 > 赋值
附录的一些琐碎的运算符知识
自增 自减 三目运算符 逗号表达式
流程控制[学习C语言的第一个重点]
1.什么是流程控制
程序代码的执行顺序
2.流程控制的分类
顺序
选择
定义
某些代码可能执行,也可能不执行,有选择的执行某些代码
分类
if
1.if最简单的用法
格式
if(表达式)
语句
功能:
如果表达式为真,执行语句
如果表达式为假,语句不执行
2.if的范围问题
1.
if(表达式)
语句A;
语句B;
解释:if默认只能控制语句A的执行或不执行
if无法控制语句B的执行或不执行
或者说:语句B一定会执行
2.if(表达式)
{
语句A;
语句B;
}
此时if可以控制语句A和语句B
由此可见:if默认只能控制一个语句的执行或不执行
如果想控制多个语句的执行或不执行
就必须把这些语句用{}括起来
3.if…else…的用法
4.if…else if…else…的用法
if(1)
A;
else if(2)
B;
else if(3)
C;
else
D;
5.C语言对真假的处理
非零是真
零就是假
真用1表示
假用0表示
6.if举例–求分数的登记
7.if 的常见问题解析
1.空语句的问题
if(3>2);
等价于
if(3>2);
; //这是一个空语句
else(表达式4);
D;
等价于
else
(表达式4);
D
switch
把电梯程序看懂就OK了
循环
定义:某些代码会被重复执行
分类
for
1.格式
for(1;2;3)
语句A;
2.执行的流程(重点)
单个for循环的使用
多个for循环的嵌套使用
for(1;2;3)
for(4;5;6)
A; B;
3.范围问题
强制类型转换
格式:
(数据类型)(表达式)
功能:
把表达式的值强制转化为前面所执行的数据类型
例子:
(int)(4.5+2.2) 最终值是6
(float)(5) 最终值是5.000000
浮点数的存储所带来的问题
float和double都不能保证可以精确的存储一个小数
举例:
有一个浮点型变量x,如何判断x的值是否是零
if(|x-0.000001|<0.000001)
是零
else
不是零
为什么循环更新的变量不能定义成浮点型
一些琐碎的运算符知识
自增【或者自减】
分类:
前自增 – ++i
后自增 – i++
前自增和后自增的异同:
相同:
最终都使i的值加1
不同
前自增整体表达式的值是i加1之后的值
后自增整体表达式的值是i加1之前的值
为什么会出现自增
代码更精炼
自增的速度更快
学习自增要明白的几个问题
1.我们编程时应该尽量屏蔽掉前自增和后自增的差别
2.自增表达式最好不要作为一个更大的表达式的一部分来使用
或者说
i++和++i单独成一个语句,不要把它作为一个完整复合语句的一部分来使用
如:
int m = i++ + ++i + i + i++;//这样写不但是不规范的代码,而且是不可移植的代码
printf(“%d %d %d”,i++,++i.i);//同上
2.三目运算符
A?B:C
等价于
if(A)
B;
else
C;
3.逗号表达式
格式
(A,B,C,D)
功能:
从左到右执行
最终表达式的值是最后一项的值
while
1.执行顺序
格式:
while(表达式)
语句;
2.与for的相互比较
for和while可以相互转换
for(1;2;3)
A;
等价于
1;
while(2)
{
A;
3;
}
while和for可以相互转化
但for的逻辑性更强,更不容易出错,推荐多使用for
3.举例
4.什么时候使用while,什么时候使用for
do-while
格式
do
{
…
}while(表达式);
do…while 并不等价于for,当然也不等价于while
主要用于人机交互
break和continue
break
break用于循环是用来终止循环
break如果用于switch,则是用于终止switch
break不能直接用于if,除非if属于循环内部的一个子句
例子:
for(i=0;i<3;i++)
{
if(3>2)
break;//break虽然是if内部的语句,但break终止的却是外部的for循环
printf(“嘿嘿!\n”);//永远不会输出
}
在多层循环中,break只能终止距离它最近的循环
例子:
for(i=0;i<3;++i)
{
for(j=1;j<4;++j)
break; //break只能终止距离它最近的那个循环
printf(“同志们好!\n”);
}
continue
用于跳过本次循环余下的语句,转去判断是否进行下一次循环
数组
int a[5]={1,2,3,4,5}; //a是数组名字,5表示数组元素的个数,并且这5个元素分别用a[0],a[1],a[2],a[3],a[4]表示
为什么需要数组
为了解决大量同类型数据的存储和使用问题
为了模拟现实世界
数组的分类
一维数组
怎样定义一维数组
为n个变量连续分配存储空间
所有的变量数据类型必须相同
所有的变量所占的字节大小必须相等
例子:
int a[5];
一维数组名不代表数组中所有的元素
一维数组名代表数组第一个元素的地址
有关一维数组的操作
初始化
完全初始化
int a[5]={1,2,3,4,5};
不完全初始化,未被初始化的元素自动为零
int a[5]={1,2,3};
不初始化,所有元素都是垃圾值
int a[5];
清零
int a[5]={0};
错误写法:
int a[5];
a[5]={1,2,3,4,5};//错误
只有在定义数组的同时才可以整体赋值,其他情况下整体赋值都是错误的
int a[5]={1,2,3,4,5};
a[5]=100;//error 因为没有a[5]这个元素,最大只有a[4]
int a[5]={1,2,3,4,5};
int b[5];
如果要把a数组中的值全部复制给b数组
错误的写法:
b=a;//error
正确的写法
for(i=0;i<5;++i)
b[i]=a[i];
赋值
排序
求最大/最小值
倒置
查找
插入
删除
二维数组
int a[3] [4];
总共是12个元素,可以当做3行4列看待,这12个元素的名字依次是
a[0] [0] a[0] [1] a[0] [2] a[0] [3]
a[1] [0] a[1] [1] a[1] [2] a[1] [3]
a[2] [0] a[2] [1] a[2] [2] a[2] [3]
a[i] [j] 表示第i +1行第j+1列的元素
int a[m] [n];该二维数组右下角位置的元素只能是a[m-1] [n-1]
初始化
int a[3] [4]={1,2,3,4,5,6,7,8,9,10,11,12};
int a[3] [4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
//输出数组内容
for (i=0;i<3;i++)
{
for(j=0;j<4;++j)
printf(“%d”,a[i] [j]);
printf(“\n”);
}
对二维数组排序
求每一行的最大值
判断矩阵是否对称
矩阵的相乘
多维数组
是否存在多维数组
不存在
因为内存是线性一维的
n维数组可以当做每个元素是n-1维数组的一维数组
比如:
int a[3] [4];
该数组是含有3个元素的一维数组
只不过每个元素都可以再分成4个小元素
int a[3] [4] [5];
该数组是含有3个元素的一维数组
只不过每个元素都是4行5列的二维数组
函数【C语言的第二个重点】:
为什么需要函数
避免了重复性操作
有利于程序的模块化
什么叫函数
逻辑上:能够完成特定功能的独立的代码单元
物理上:能够接收数据【当然也可以不接受数据】
能够对接受的数据进行处理
能够对数据处理的结果返回【当然也可以不返回任何值】
总结:函数是个工具,他是为了解决大量类似问题而设计的
函数可以当做一个黑匣子
如何定义函数
函数的返回值 函数的名字(函数的形参列表)
{
函数的执行体
}
1.函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体实现方法
2.return 表达式; 的含义:
1>终止被调函数,向主调函数返回表达式的值
2>如果表达式为空,则只终止函数,不向被调函数返回任何值
3>break是用来终止for循环和switch的,return是用来终止函数的
例子:
void f()
{
return; //return只用来终止函数,不向主调函数返回任何值
}
int f()
{
return 10; //第一:终止函数,第二:向主调函数返回10
}
3.函数返回值的类型也称为函数的类型,如果函数名前的返回值类型和函数执行体中的return 表达式; 中表达式的类型不同的话,则最终函数返回值的类型,以函数名前的返回值类型为准
例子:
int f()
{
return 10,5; //因为函数的返回值类型是int
//所以最终f返回的是10而不是10.5
}
函数的分类
有参函数 和 无参函数
有返回值 和 无返回值函数
库函数 和 用户自定函数
值传递函数 和 地址传递函数
普通函数 和 主函数(main函数)
一个程序必须有且只能有一个主函数
主函数可以调用普通函数 普通函数不能调用主函数
普通函数可以相互调用
主函数是程序的入口,也是程序的出口
注意的问题
函数调用和函数定义的顺序
如果函数调用写在了函数定义的前面,则必须加函数前置声明
函数前置声明:
1.告诉编译器即将可能出现的若干个字母代表的是一个函数
2.告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况
3.函数声明是一个语句,末尾必须加分号
4.对库函数的声明是通过#include<库函数所在的文件的名字.h>来实现的
形参和实参
个数相同 位置一一对应 数据类型必须相互兼容
如何在软件开发中合理的设计函数来解决实际问题
一个函数的功能尽量独立,单一
多学习,多模仿牛人的代码
函数是C语言的基本单位,类是Java,C#,C++的基本单位
常用的系统函数
double sqrt(double x);
求的x的平方根
int abs(int x)
求x的绝对值
double fabs(double x)
求x的绝对值
专题:
递归
变量的作用域和存储方式:
按作用域分:
全局变量
在所有函数外部定义的变量 称为全局变量
全局变量适用范围:从定义位置开始到整个程序结束
局部变量
在一个函数内部定义的变量或者参数的形参 都统称为局部变量
void f(int i)
{
int j = 20;
}
i和j都属于局部变量
局部变量使用范围:只能在本函数内部使用
注意的问题:
全局变量和局部变量命名冲突的问题
在一个函数内部如 果定义的局部变量的名字和全局变量一样时,局部变量会屏蔽掉全局变量
按变量的存储方式
静态变量
自动变量
寄存器变量
指针:
指针的重要性:
表示一些复杂的数据结构
快速的传递数据,减少了内存的耗用
使函数返回一个以上的值
能直接访问硬件
能够方便的处理字符串
是理解面向对象语言中引用的基础
总结:指针是C语言的灵魂
指针的定义
地址
内存单元的编号
从零开始的非负整数
范围:4G【0–4G-1】
指针
指针就是地址,地址就是指针
指针变量就是存放内存单元编号的变量,或者说指针变量就是存放地址的变量
指针和指针变量是两个不同的概念
但是要注意:通常我们叙述时会把指针变量简称为指针,实际他们的含义不一样
指针的本质就是一个操作受限的非负整数
指针的分类
1.基本类型指针
#include<stdio.h>
int main(void)
{
int * p;//p是变量的名字,int*表示p变量存放的是int类型变量的地址
//int * p;不表示定义了一个名字叫做*p的变量
//int * p; 应该这样理解:p是变量名,p变量的数据类型是int *类型
// 所谓int *;类型 实际 就是存放int变量地址的类型
int i = 3;
p = &i;
/*
1.p保存了i的地址,因此p指向i
2.p不是i,i也不是p,更准确的说:修改p的值不影响i的值,修改i的值不影响p的值
3.如果一个指针变量指向了某个普通变量,则
*指针变量 就完全等同于 普通变量
例子:
如果p是个指针变量,并且p存放了普通变量i的地址,则p指向了普通变量i
*p就完全等同于i
或者说:在所有出现*p的地方都可以替换成i
在所有出现i的地方都可以替换成*p
*p就是以p的内容为地址的变量
j=*p;//等价于j=i;
printf("i=%d.j=%d\n,i,j");
}
附注:
*的含义
1.乘法
2.定义指针变量
int *p;//定义了一个名字叫p的变量,int*表示只能存放int变量的地址
3.指针运算符
该运算符放在已经定义好的指针变量的前面,如果p是一个定义好的指针变量,则*p表示 以p的内容为地址的变量
如何通过被调函数修改主调函数普通变量的值
1.实参必须为该普通变量
2.形参必须为指针变量
3.在被调函数中通过
*形参名=......
的方式就可以修改主调函数相关变量的值
2.指针和数组
指针和一维数组
一维数组名
一维数组名是个指针常量
它存放的是一维数组第一个元素的地址
下标和指针的关系
如果p是个指针变量,则
p[i]永远等价于*(p+i)
确定一个函数要处理一个一维数组需要几个参数【如果一个函数要处理一个一维数组,则需要接收该数组】
需要两个参数:
数组第一个元素的地址
数组的长度
指针变量的运算
指针变量不能相加 不能相乘 也不能相除
如果两个指针变量指向的是同一块连续空间中的不同存储单元,则这两个指针变量才可以相减
一个指针变量到底占几个字节【非重点】
预备知识:
sizeof(数据类型)
功能:sizeof(int)=4 sizeof(char) = 1
sizeof(double) = 8
sizeof(变量名)
功能:返回值是该变量所占的字节数
假设p指向char类型变量(1个字节)
假设q指向int类型变量(4个字节)
假设r指向double类型变量(8个字节)
p q r本身所占的字节数是否一样
答案:p q r 本身所占的字节数是一样的
总结:
一个指针变量,无论它指向的变量占几个字节,该指针变量本身只占四个字节
一个变量的地址,是用该变量的首字节的地址来表示
指针和二维数组
3.指针和函数
4.指针和结构体
5.多级指针
专题:
动态内存分配 【重点难点】
传统数组的缺点:
1.数组长度必须实现制定,且只能是常整数,不能是变量
例子:
int a[5];//OK
int len=5;int a[len]; //error
2.传统形式定义的数组,该数组的内存程序员无法手动释放
数组一旦定义,系统为该数组分配的存储空间就会一直存在,除非数组所在的函数运行结束
在一个函数运行期间,系统为该函数中数组分配的空间会一直存在,知道该函数运行完毕时,数组的空间才会被系统释放
3.数组的长度一旦定义,其长度就不能再更改
数组的长度不能在函数运行的过程中动态的扩充或缩小
4.A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕后,A函数中的数组无法再被其他函数使用
传统方式定义的数组不能跨函数使用
为什么需要动态分配内存
动态数组很好的解决了传统数组的这4个缺陷
传统数组也叫静态数组
动态内存分配举例_ 动态数组的构造
malloc
静态内存和动态内存的比较
跨函数使用内存的问题
结构体
为什么需要结构体
为了表示一些复杂的事物,而普通的基本类型无法满足实际要求
什么叫结构体
把一些基本类型组合在一起形成的一个新的复合数据类型,这个叫做结构体
如何定义结构体
3种方式
怎样使用结构体变量
赋值和初始化
定义的同时可以整体赋初值
如果定义完之后,则只能单个的赋初值
如何取出结构体变量中的每一个成员【重点】
1.结构体变量名.成员名
2.指针变量名->成员名(第二种方式更常用)
指针变量名->成员名 在计算机内部会被转化成(*指针变量名).成员名 的方式来执行
所以说这两种方式是等价的
例子:
struct Student
{
int age;
float score;
char sex;
};
int main(void)
{
struct Student st = {80,66.6,‘F’};//初始化 定义的同时赋初值
struct Student *pst = &st; // &st不能改成st
pst->age=88;//第二种方式
st,age=10;//第一种方式
return 0;
}
1.
pst->age 在计算机内部会被转化成(*pst).age,没有什么为什么, 这就是->的含义,也是一种硬性规定
2.
所以pst->age等价于(*pst).age也等价于st.age
3.
我们之所以知道pst->age等价于st.age,是因为pst->age是被转化成了(*pst).age来执行
4.pst->age的含义:
pst所指向的那个结构体变量中的age这个成员
结构体变量和结构体变量指针作为函数参数传递的问题
推荐使用结构体变量作为函数参数来传递
结构体变量的运算
结构体变量不能相加,不能相减,也不能相互乘除,但结构体变量可以相 互赋值
例子:
struct Student
{
int age;
char sex;
char name[100];
};//分好不能省
struct Student st1,st2;
st1+st2 st1*st2 st1/st2 都是错误的
st1-st2 或者st2=st1 都是正确的
举例
动态构造存放学生信息的结构体数组
动态构造一个数组,存放学生的信息
然后按分数排序输出
枚举
什么是枚举
把一个事物所有可能的取值一一列举出来
怎样使用枚举
枚举的优缺点
代码更安全
书写麻烦
位运算符:
专题
补码:
原码
也叫 符号-绝对值码
最高位0表示正 1表示复,其余二进制位是该数字的绝对值的二进制位
原码简单易懂
加减运算复杂
存在加减乘除四种运算,增加了CPU的复杂度
零的表示不唯一
反码
反码运算不便,也没有在计算机中应用
移码
移码表示数值平移n位,n称为移码量
移码主要用于浮点数的阶码的存储
补码
十进制转二进制
求正整数的二进制
除2取余,直至商为零,余数倒序排序
求负整数的二进制
先求与该负数相对应的正整数的二进制代码,然后将所有取反,末尾加1,不够位数时,左边补零
求零的二进制
全是零
已知二进制求十进制
如果首位是0.则表明是正整数,按普通方法来求
如果首位是1,则表明是负整数
将所有位取反,末尾加1,所得数字就是该负数的绝对值
如果全是零,则对应的十进制数字就是零
学习目标:
在vc++6.0中一个int类型的变量所能存储的数字的范围是多少
int类型变量所能存储的最大正数用十六进制表示是:7FFFFFFF
int类型变量所能存储的绝对值最大的负整数用十六进制表示是:80000000
绝对值最小负数的二进制代码是多少
最大正数的二进制代码是多少
已知一个整数的二进制代码求出原始的数字
数字超过最大正数会怎样
不同类型数据的相互转化
进制转换 【ppt】
字符串的处理
链表:
算法:
通俗定义:
解题的方法和步骤
狭义定义:
对存储数据的操作
对不同的存储结构,要完成某一个功能所执行的操作是不一样的
比如:
要输出数组中所有的元素的操作和
要输出链表中所有元素的操作肯定是不一样的
这说明:
算法是依附于存储结构的
不同的存储结构, 所执行的算法是不一样的
广义定义:
广义的算法也叫泛型
无论数据是如何存储的,对该数据的操作都是一样的
我们至少可以通过两种结构来存储数组
数组
优点:
存取速度快
缺点:
需要一个连续的很大的内存
插入和删除元素的效率很低
链表
专业术语:
头节点
头结点的数据类型和首节点的类型是一模一样的
头结点是首节点前面的那个节点
头结点并不存放有效数据
设置头结点的目的是为了方便对链表的操作
头指针
存放头结点地址的指针变量
确定一个链表需要一个参数
头指针
优点:
插入删除元素效率高
不需要一个连续的很大的内存
缺点:
数字就是零
学习目标:
在vc++6.0中一个int类型的变量所能存储的数字的范围是多少
int类型变量所能存储的最大正数用十六进制表示是:7FFFFFFF
int类型变量所能存储的绝对值最大的负整数用十六进制表示是:80000000
绝对值最小负数的二进制代码是多少
最大正数的二进制代码是多少
已知一个整数的二进制代码求出原始的数字
数字超过最大正数会怎样
不同类型数据的相互转化
进制转换 【ppt】
字符串的处理
链表:
算法:
通俗定义:
解题的方法和步骤
狭义定义:
对存储数据的操作
对不同的存储结构,要完成某一个功能所执行的操作是不一样的
比如:
要输出数组中所有的元素的操作和
要输出链表中所有元素的操作肯定是不一样的
这说明:
算法是依附于存储结构的
不同的存储结构, 所执行的算法是不一样的
广义定义:
广义的算法也叫泛型
无论数据是如何存储的,对该数据的操作都是一样的
我们至少可以通过两种结构来存储数组
数组
优点:
存取速度快
缺点:
需要一个连续的很大的内存
插入和删除元素的效率很低
链表
专业术语:
头节点
头结点的数据类型和首节点的类型是一模一样的
头结点是首节点前面的那个节点
头结点并不存放有效数据
设置头结点的目的是为了方便对链表的操作
头指针
存放头结点地址的指针变量
确定一个链表需要一个参数
头指针
优点:
插入删除元素效率高
不需要一个连续的很大的内存
缺点:
查找某个位置的元素效率低