C语言程序和程序设计概述
程序:可以连续执行的一条条指令的集合
开发过程:C源程序(.c文件) --> 目标程序(.obj二进制文件,目标文件) --> 可执行文件(.exe文件) -->结果
在任何机器上可以运行C源程序生成的 .exe 文件
没有安装C语言集成开发环境,不能编译C语言程序,函数
是C程序的基本单位
程序设计有以下几个部分:
- 确定数据结构
- 确定算法
- 编码(编写代码)
- 计算机上调试程序
- 整理并写出文档资料
C语言运行方法:编译执行,python:解释执行
头文件:#include<stdio.h>
C语言的结构特点:
- 函数是C程序的主要组成部分
一个C程序是由一个或多个函数组成
必须包含一个main函数(只能有一个)
每个函数都用来实现一个或多个特定功能
被调用的函数可以是库函数,也可以是自己编制设计的函数
- 程序总是从main函数开始执行
- C程序书写可以一行内写几个语句,也可以一个语句分写在多行上(以分号为标准,判断是否是一个语句)
- 数据声明和语句最后必须有分号
- C语言本事不提供输入输出语句,由库函数提供
算法表示方法:
- 自然语言
- 用伪代码表示
- 用流程图表示
- N-S流程图表示
标识符、常量和变量
常量
整型常量:12、0、-3
实型常量:
十进制小数:0.34、-56.79
指数形式:12.34e3(12.34×10³)
符号常量:‘a’、‘b’
字符串常量:“Beijing”
常量在程序运行期间,值不可以改变的
#define PI 3.14159 //定义符号常量不需要分号
变量
在程序运行期间,值是可以改变的
定义变量时指定该变量的名字和类型
变量名实际上是以一个名字代表一个存储地址
从变量取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据
标识符
只能由字母、数字和下划线组成,且第一个字符必须为字符或下划线,不能使用C语言关键字作为标识符
C语言是严格区分字母大小写
关键字必须用小写字母
数据类型
整型数据
整型常量3种表示形式
十进制整数,如2,-983
八进制整数。以0开头,由0~7构成,通常为无符号数,如012,八进制12
十六进制整数。以0x开头,由 0 ~ 9 和 A ~ F 或 a ~ f 构成,如0x12A,十六进制12A
整型变量:类型说明符 变量名标识符; 如 int a,b,c;
在定义变量的同时给变量赋初值,称变量初始化,若没有初始化,则内容不确定
计算机最小存储单位:位(bit)
一个字节(byte) = 8bit
关键字 | 类型 | 所占的空间 |
---|---|---|
char | 字符串类型 | 占1字节空间(8位二进制位) |
short | 短整型 | 占2字节空间(16位二进制位) |
int | 整型 | 占4个字节空间(32位二进制) |
long | 长整型 | 占4个字节空间(32位二进制)(在64为平台下占8个字节) |
float | 单精度浮点数 | 占4个字节空间(32为二进制)(7位有效位,指数-37到38) |
double | 双精度浮点数 | 占8个字节空间(64为二进制)(16位有效位,指数-307到308) |
在存储有符号数时,存储单元最高为代表符号位,0为正,1为负
设计程序时,注意变量类型的取值范围,当赋值超过取值范围时,会出现溢出错误
一个整 型常量后加 U或u 后缀则被认为时unsigned类型,内存中按unsigned规定方式存放
一个整型常量后加 L或l 后缀则被认为时long类型,内存中按long规定位数存放
无符号长整数:用后缀 UL/ul表示,如:15ul
浮点型(实型)数据
实型常量
又称实属或浮点数
十进制小数形式,如123.456
指数形式:以 “e” 或 “E” 后跟一个整数来表示以10为底的幂数,如 2.3026e2
规定:字母 e 或 E 之前必须有数字,且e或E后面指数必须为整数
10⁸不能写成e8,必须写成:1e8 或 1.0E8
实型变量
实型(3.14159)数据在内存中存放的形式:
+:数符
.314159:小数部分
1:指数
小数部分占的为数越多,数的有效数字越多,精度越高
指数部分占的位数越多,则能表示的数值范围越大
字符型数据
字符常量
用单引号括起来的一个字符,如’a‘、’E‘,不能 ’ab‘
字符常量以ASCII码存储,一个字符占一个字节,大写字母与小写字母ASCII码值相差 32
字符变量
如:char c1,c2,c3; c1 = ‘A’; c2 = ‘\n’;
每个字符变量分配一个字节用于存放一个字符(存放的是字符的ASCII码值)
字符数据与整型数据可相互赋值,直接运算
用%d输出,则输出整型数,用%c输出,则输出字符
字符串常量
一对双引号(" ")括起来的字符序列,字符个数称为其长度,如:“hellow”
长度为n的字符串,在计算机存储中占n+1个字节,原因:会自动在结尾添加 ’\0‘
ASCII码表
转义字符
字符形式 | 功能 | 字符形式 | 功能 |
---|---|---|---|
\n | 回车换行 | \\ | 一个反斜杠字符(\) |
\t | 将当前位置移到下一个tab位置 | \’ | 一个单引号(') |
\v | 当前位置移到下一个垂直制表对齐点 | \" | 一个双引号(") |
\r | 回车符 | \ddd | 三位八进制数代表一个ASCII字符 |
\f | 换页符 | \xhh | 二位十六进制代表一个ASCII字符 |
\b | 将当前位置后退一个字符 | \0 | 空值,其ASCII码值为0 |
符号常量
用标识符表示的常量,一般符号常量名用大写字母表示,命令通常放在文件头,在程序中不允许重新赋值,注意:不需要分号结尾
格式:#define 标识符 常量 如:#define PI 3
数学函数
运算符和表达式
算术运算符
优先级越小,越优先,优先级相同时,运算次序由结合性决定
运算符 | 运算规则 | 操作数数目 | 优先级 | 结合方向 |
---|---|---|---|---|
- | 负号 | 单目 | 2 | 左结合 |
+ | 加法 | 双目 | 4 | 左结合 |
- | 减法 | 双目 | 4 | 左结合 |
* | 乘法 | 双目 | 3 | 左结合 |
/ | 除法 | 双目 | 3 | 左结合 |
% | 取余或模 | 双目 | 3 | 左结合 |
1./3 + 1./3 + 1./3 = 1
取余运算符,所得结果的符号与运算符左侧操作数符号相同,如:-5 % 2 = -1,5 % -2 = 1,运算对象只能是整型
,结果也是整型,如:5 % 2 =1
自增、自减运算符
自增和自减运算符只能用于变量,不能用于常量和表达式
含义 | 运算符 | 优先级 | 结合性 | 功能 |
---|---|---|---|---|
自增 | ++ | 2 | 右结合 | 使变量的值增1 |
自减 | – | 2 | 右结合 | 使变量的值减1 |
使用形式:
++i 或 --i 变量 i 先自增或自减 1,再引用 i
i++ 或 i-- 先使用变量 i,再自增或自减1
不同数据类型间的转换
自动转换类型:数据类型自动由低级向高级转换
强制转换:将表达式的运算结果强制转换成指定的数据类型
格式:(数据类型说明符)(表达式)
int x,y;
float z;
(float)(x+y); //浮点型
(int)z+x; //整型
关系运算符(比较运算)
关系表达式:
格式:表达式1 关系运算符 表达式2; 如:m+n <= 20; 成立表达式值为 1,不成立值为0
含义 | 运算符 | 优先级 | 结合性 |
---|---|---|---|
小于 | < | 6 | 左结合 |
小于等于 | <= | 6 | 左结合 |
大于 | > | 6 | 左结合 |
大于等于 | >= | 6 | 左结合 |
等于 | == | 7 | 左结合 |
不等于 | != | 7 | 左结合 |
逻辑运算符
含义 | 运算符 | 优先级 | 结合性 | 运算逻辑 |
---|---|---|---|---|
逻辑非 | ! | 2 | 右结合 | 取反 |
逻辑与 | && | 11 | 左结合 | 全真为真,其余为假 |
逻辑或 | || | 12 | 左结合 | 全假为假,其余为真 |
逻辑表达式
形式:表达式1 逻辑运算符 表达式2 如:5 > 3 && 2 || 4 - !‘a’
判断时,0 代表 假,非0 代表真
逻辑与 和 逻辑或 短路能力
逻辑与:只有表达式1值为真,才求表达式2 的值
逻辑或:只有表达式1值为假,才判断表达式2的值
三目表达式
形式:表达式1 ? 表达式2 : 表达式3 如:max = (a>b)?a:b;
如果表达式1为真,执行表达式2,为假,执行表达式3
最终判断出的值类型,为表达式2和表达式3 中较高的类型
可以嵌套的,这种嵌套是右结合,如:a > b ? c : c > d ? b : d;
赋值运算符
复合赋值运算符:+=、-=、*=、/=、%= 优先级14,右结合性
赋值表达式
简单赋值表达式
格式:变量 = 表达式 如:k = i++±-j
执行顺序:先计算,再赋值
复合表达式
x += y += z*z --> x= x+(y=y+z*z)
逗号运算符
符号:,
优先级15,左结合
逗号表达式
格式:表达式1,表达式2,表达式3 如:a = 3*5,a*10,a+8
求解过程中:先求表达式1的值,再表达式2的值,再表达式n的值,表达式n的值作为整个逗号表达式的值
选择结构(分支结构)
if语句
格式:
if(表达式) 语句1; //语句1,只能是一条语句
if(表达式)
{
语句块1;
}
if()
{
}
else if()
{}
else
{}
if()
{
if()
{}
}
注意:else 与 if 必须成对出现,且else总是与最近的一个未配对的 if 配对
switch语句
格式:
switch(表达式) //表达式类型要与case后面常量值类型匹配,只能是整型、字符型或枚举型
{
case 常量表达式: //每个case后的常量表达式不允许相同
语句1;
break;
case 常量表达式:
语句2;
break;
......
default:
语句n+1;
}
break语句终止switch语句的执行
循环结构
while语句
格式:
while(表达式)
{
语句块; //循环体
}
//先判断,再执行,有可能一次也不执行
注意:
1)while没有初始化语句,用户提前初始化好
2)while没有步进语句,用户必须在循环语句中写好步进语句
3)循环变量的值可以被引用、修改,但不能赋新值
#include <stdio.h>
void test04()
{
int i = 0;
int sum = 0;
while(i<=100)
{
sum += i;
i++; //步进条件
}
printf("sum = %d\n",sum); //sum = 5050
}
int main(int argc,char *argv[])
{
test04();
}
//当循环体是空语句或单个语句
while(x++ < 1000); //分号不能省略
x = 10;
while(x-- > 0)printf("%d",x);
do-while语句
格式:
do
{
//循环体语句
}while(表达式);
//特点:先执行,再判断,至少执行一次循环体
for语句
格式:
for(初始语句;循环条件;步进条件)
{
//循环语句
}
//初始语句:只在循环开始时执行一次
//循环条件: 每次循环都要执行,如果循环条件为 真 进入循环体,如果为 假 退出循环
//步进条件:每次循环结束的时候要执行的语句
//初始语句可以省略,但要在for语句之前给循环变量赋初值
//循环条件为空时,则会陷入死循环
//进步条件省略时,需要在循环体内写进步条件
//初始语句和进步条件可以有多项,若有多项则使用逗号表达式
for(s = 0,i = 1;i <= 100;s += i,i++);
//单个语句时
for(初始语句;循环条件;步进条件)
语句;
//特点:先判断,再执行,有可能一次也不执行
嵌套for循环:总结外层循环的次数*内层循环的次数==总循环次数
//并列的循环变量可以同名,但嵌套的循环变量不能同名
for(初始语句;循环条件;步进条件)
{
for(初始语句;循环条件;步进条件)
{
//循环语句
}
}
break语句
格式:break;
作用:提前退出某个循环或跳出switch结构
只能在switch语句和循环体中使用
continue语句
格式:continue;
作用:结束本次循环,接着下次循环,通常与if语句连用
数组与结构
一维数组
格式:类型说明符 数组名[常量表达式];
常量表达式可以是 正整数常量、符号常量或常量表达式,不能包含变量
#define N 10
int a[11],b[N],c['0'];
float d[2*N];
//sizeof(类型) * 数组长度 = 总字节数
int(4字节) * 11 = 44
//引用方式
数组名 [下标]
//数组初始化
类型符 数组名[表达式] = {初值表};
//全部元素赋初值
int a[8] = {0,1,2,3,4,5,6,7}; //初始数据个数>数组长度,编译出错
//部分元素赋初值
int a[8] = {0,1,2,3,4}; //剩下元素的初值为0
//给全部元素赋初值时可以不指定数组长度
int a[] = {1,2,3,4,5,6,7}; //数组长度是初值表中数值的个数
//当对全部数组元素初始化为0时,可以写成
int x[5] = {0,0,0,0,0};
或 int x[5] = {0};
//初值表不能为空 如:int a[5] = {}; 但是可以int a[5]; 但元素值不确定
//如果没有初始化的数组,元素的值不确定
数组是数目固定,类型相同的若干变量的有序集合
数组中每一个变量称为数组元素,属于同一个数据类型
数组在内存占有一段连续的存储空间
二维数组
格式:类型说明符 数组名[常量表达式1] [常量表达式2]; 如:int a[3][4];
注意:下标从0开始
二维数组总字节数:行数 * 列数 * 类型字节数
字符数组
标准库
//如使用输入输出函数
#include<stdio.h>
//使用字符串处理函数
#include<string.h>
//使用数学库中的函数
#include<math.h> //所有数学函数返回都是double型
C语言中将 null 定义为 0,则null表示则为0
EOF:为-1
数据结构
课件:https://maifile.cn/est/a65c2e423881c5/pdf
第二章 线性表
线性表定义:n(>= 0)个数据特性相同的元素的有限序列,记作(a1,a2,…,an)
线性表逻辑结构:一对一
ai是表中数据元素,n是表长度
遍历:逐项访问,从前向后,从后向前
线性表特点:
除了第一个元素外,其他每一个元素有且只有一个直接前驱
除了最后一个元素外,其他每一个元素有且只有一个直接后驱
例:a1<–>a2<---->a3<---->a4
线性表的存储结构:顺序存储结构、链式存储结构(单链表、双链表、循环链表)
顺序表(顺序存储):
每个节点只存放数据元素
定义:将线性表中的元素相继存放在一个连续的存储空间中
特点:线性表的顺序存储方式,可以随机存取
优点:可随机存取,存储密度高
缺点:要求大片连续空间,改变容量不方便
插入/删除 要将后续元素后移/前移动,可通过下表确定目标元素位置,时间开销主要移动元素(O(n))
按位查找 O(1) ,按值查找(需要对元素值一一比较) O(n)
链表(链式存储)
每个节点除了存放数据元素外,还存储向下一个节点的指针
优点:不要求大片连续空间,改变容量方便
缺点:不可随机存取,要耗费一定空间存放指针
单链表:无法逆向检索,增加头节点目的:方便运算的实现(使得对第一个元素的操作与其他元素操作相同)
双链表:可进退检索
空表:头节点指针域都指向头节点
循环单链表:表尾节点的指针指向头节点,形成循环
循环双链表:双向指针域,尾节点指向头节点,头节点指向下一个节点和尾节点,形成循环且可进退
复杂度:若从头节点找到尾部,时间复杂度为O(n),n:n个元素
插入/删除 元素只需修改指针即可,但需要遍历找到对应修改元素的位置,时间开销主要查找目标元素(O(n))
按位查找 O(n) ,按值查找 O(n)
总结:
链表:用于经常需要增加/删除元素(弹性)
顺序表:用于查询(搜索)操作
栈:先进后出
(全部元素不用全部进栈才可以出栈,进栈和出栈的顺序可组成不同的序列)
压栈(push),出栈(pop)
队列:先进先出
栈和队列的共同点:只允许端点处插入和删除元素,都是线性表
括号配对算法结构:栈 最佳
串和广义表
串
串或字符串:由零个或多个字符组成的有限序列
串也称为字符串,在 C 语言中是由数字、字母、下划线以及特殊字符组成的串字符,字符串需要用一对双引号括起来。在一个字符串中取一部分作为一个新字符串,这个新字符串叫子串,另一个叫做它的母串
s = “a₁ a₂ a₃ … an” (n >= 0) n为串的长度
子串:串中任意个连续字符组成的子序列,包含字串的串称为主串
空串:零个字符的串
例:a = “BEI” b = “JING” c = “BEIJING” d = “BEI JING”
a和b都是c和d的字串,a在c和d中的位置都是1,b在c中的位置是4,在d中的位置是5
只有两个串的长度相等,并各个对应位置的字符都相等时,则这两个串都是相等的
广义表
定义:广义表是线性表的推广,也称为列表
广义表的深度,可以通过观察该表中所包含括号的层数间接得到
如:{{1,2},{3,{4,5}}} 中,子表 {1,2} 和 {3,{4,5}} 位于同层,此广义表中包含 3 层括号,因此深度为 3
广义表的长度(广度):广义表中所包含的数据元素的个数
如:广义表 {{a,b,c}} 中只有一个子表 {a,b,c},因此它的长度为 1
树
树的逻辑结构:一对多
空树:节点数为0的树
有且只有一个根节点
没有后继的节点:叶子节点
有后继的节点:分支节点
除了根节点外,任何一个节点有且只有一个前驱
每个节点可以有 0 个或 多个后继
路径:由一节点到另一节点间的分支构成(只能从上往下)
路径长度:路径上的分支数目(经过几条边)
树的路径长度:树中所有叶子节点到根的路径长度之和
节点的层次(深度):从上往下数
节点的高度:从下往上数
树的高度(深度):总共有多少层
节点的度:有几个孩子(分支)
树的度:各节点的度的最大值
树的性质:
总点数 = 总度数 + 1
m叉树:每个节点最多只能有m个孩子的树,可以是空树
度为 m 的树第 i 层最多有 m的 i-1 次方 个节点
m叉树第 i 层最多有 m的 i-1次方
个节点
高度为 h 的m叉树至多有几个节点(每一层都最多,则使用每层计算最多节点的方法再相加)
高度为 h 的m叉树至少有 h 个节点
高度为 h,度为m的树至少有 h+m-1
个节点
具有n个节点的m叉树的最小高度? 每一层节点打满
二叉树
特点:每个节点至多只有两颗子树,左右子树不能颠倒(二叉树是有序树)
任意二叉树满足:n0 = n2 + 1
二叉树转森林:二叉树从根(包含)开始路过几个节点就有几个根,也就是有森林有几棵树
满二叉
一颗高度为h,含有 2的h次方-1
个节点的二叉树
特点:
只有最后一层有叶子节点
不存在度为1 的节点
按层序从1开始编号,节点 i 的左孩子为 2i,右孩子为 2i + 1,节点i的父亲节点为 i/2(向下取整)
完全二叉树
在满二叉树的基础上可去掉若干个编号更大的节点(最后几个缺失),某节点只有一个孩子,一定是左孩子
高度:H = ㏒₂N + 1
特点:
只有最后两层可能有叶子节点
最多只有一个度为 1 的节点
按层序从1开始编号,节点 i 的左孩子为 2i,右孩子为 2i + 1,节点i的父亲节点为 i/2(向下取整)
i <= n/2 为分支节点,i > n/2 为叶子节点 n:节点数
二叉排序树
左子树上所有节点的关键字均小于根节点的关键字
右子树上所有节点的关键字均大于根节点的关键字
左子树和右子树又各是一颗二叉排序树
判断二叉排序树的元素大小
在树图下方画个向右的坐标轴,从图中对应元素垂直到坐标轴,则可得到元素从小到大排序
查找(考察比较次数 == 查找长度)
从上往下寻找,左树比根小,右数比根大,查找成功,返回结点指针,查找失败,返回null
查找成功时 平均查找长度(ASL): 每层的 查找长度 * 节点数 相加 / 节点数
查找失败时 平均查找长度(ASL): 有叶子节点每一层的 同一层叶子节点数 * 查找长度 相加 / 总叶子节点数
平衡二叉树
平衡二叉树是排序二叉树的特殊情况
树上,任一节点的左子树和右子树的深度之差不超过1
节点平衡因子 = 左子树高 - 右子树高,只能是 -1 0 或 1
二叉树遍历
都是先左树后右树
先序遍历:根左右(从上到下,从左到右)
中序遍历:左根右(小嵌套再大嵌套)
后续遍历:左右根(小嵌套再大嵌套)
层序遍历:从上到下,从左到右
只给出前、中、后、层序遍历序列中的一种,可能对应多种二叉树形态,所以不能确定唯一一颗二叉树
需要两种来确定唯一(给出两个序列画图)
前序(确根) + 中序遍历(确左右)
后序(确根) + 中序遍历(确左右)
层序 + 中序遍历
哈夫曼树
结点的权(节点上面的数值):有某种显示含义的数值(如:表示结点的重要性等)
结点
的带权路径长度:从树的根到该结点的路径长度(经过边数) 与 该结点上权值
的乘积
树
的带权路径长度(WPL):树中所有叶子结点
的带权路径长度之和
定义:含有n个带权叶子结点的二叉树中,其中树的带权路径长度最小
的二叉树,哈夫曼树(最优二叉树)
构造
选取权值最小
的结点构成新结点,新结点的权值为左 右子树上根结点权值之和,直到全部结点拼接完
特点:
每个初始结点(给出)最终都成为叶子结点,且权值越小的结点到根结点的路径长度越大
哈夫曼树的结点总数为:2n-1 n:初始结点数
哈夫曼树中不存在度为 1 的结点
哈夫曼树并不唯一,但WPL(树的带权路径长度)必然相同且最优
哈夫曼编码
固定长度编码:每个字符用相等长度的二进制表示
可变长编码:允许对不同字符用不等长的二进制位表示(使用哈夫曼树编辑二进制位)
前缀编码:没有一个编码是另一个编码的前缀,无歧义。非前缀编码有歧义
哈夫曼编码可以用于数据压缩
图
图(G)由顶点集(V)和边集(E)组成,|V|:图中顶点的个数 |E|:图中边的条数
元素存在多对多
的关系
图不可以是空,即 V 一定是非空集,但E可为0
有向图:边是有方向的(有向边)
G = (V,E)
V = {A,B,C,D,E}
E = {<A,B>,<A,C>,<A,D>,<A,E>,<B,A>,<B,C>,<B,E>,<C,D>}
无向图:边是没有方向的(无向边)
G = (V,E)
V = {A,B,C,D,E}
E = {(A,B),(B,D),(B,E),(C,D),(C,E),(D,E)}
简单图:不存在重复边,不存在顶点到自身的边(有向图中两个方向不同的边不属于重复边)
多重图:两个结点之间边数多余一条,允许顶点通过同一条边和自己联系
对于无向图
顶点的度:依附于该顶点的边的条数
无向图的全部顶点的度的和 等于 边数的2倍
对于有向图
入度(进来):顶点 v 为终点的有向边的数目
出度(出去):顶点 v 为起点的有向边的数目
顶点v的度:入度和出度之和 入度之和 = 出度之和 = 边数
路径:顶点到顶点之间的路径
回路或环:第一个顶点和最后一个顶点相同的路径(构成闭环)
简单路径:顶点不重复出现的路径
简单回路:除了第一个顶点和最后一个顶点外,其余顶点不重复出现的回路
路径长度:路径上 边的数目
点到点的距离:顶点u到顶点v的最短路径若存在,则此路径的长度为u到v的距离,若不存在,则该距离为无穷(∞)
无向图中,顶点v 到 顶点w 有路径存在,则称 v 和 w 是连通的
有向图中,顶点v 到 顶点w 和 顶点w 到 顶点v 之间都有路径,则这两个顶点为强连通的
若图(无向)中,任意两个顶点都是连通的,则成为连通图,否则为非连通图
对于n个顶点的无向图G
若G是连通图,则最少有 n-1
条边
若G是非连通图,则最多可能有n(n-1)/2
若图(有向)中,任何一堆顶点都是强连通,则此图为强连通图
n个顶点的强连通图,最少有n
条边(形成回路)
生成子图:无向图中包含全部点(父图)
连通分量:无向图中有几个分开的整体,几个整体就是连通分量
强连通分量:有向图中有几个分开的整体,几个整体就是连通分量
连通图生成树:包含图中全部顶点,边尽可能少,但要保持连通
无向全连通图边数:n(n-1)/2
n:顶点数
n个顶点有向图,每个顶点的度最大可达 2(n-1)
图的存储
邻接矩阵法
注意:有向图的方向,无向图
斜角45度对称
在无向图中,第i个结点的度 = 第i行(或者第i列)的非零元素个数
在有向图中,第i个结点的出度 = 第i行的非零元素个数
第i个结点的入度 = 第i列的非零元素个数
第i个结点的度 = 第i行、第i列的非零元素的个数之和
邻接矩阵法求顶点的度 出度 入度 的时间复杂度为 O(|v|) v:顶点个数
邻接矩阵法:所占存储空间与顶点个数相关
结点数为n,邻接矩阵A是 n*n 的
邻接矩阵法存储带权图
邻接矩阵图性能分析
空间复杂度:O(|v|²) v:顶点数 只和顶点数有关,和实际边数无关
适合用于存储稠密图
无向图
的的邻接矩阵是对称矩阵
,可以压缩存储
邻接表(顺序+链式存储)
边结点的数量是2|E| (每条边被记录了两次)
无向图空间复杂度为:O(|v| + 2|E|)
有向图空间复杂度为:O(v+e)
排列方式:不唯一
。存储稀疏图(边较少)
图的遍历
可能序列排序不唯一,按节点编号的升序
一次访问
广度优先遍历(BFS)
树:类似层序遍历
,一层一层遍历,先孩子再孙子,按编号升序访问
时间复杂度:O(n+e) n:顶点数 e:边数
使用队列
数据结构
深度优先遍历(DFS)
树:类似先序遍历
,一条直线走到底,走完再换另一个,按编号升序访问方向
时间复杂度:O(n+e) n:顶点数 e:边数
使用栈
数据结构,是一个递归过程
图:
广度优先:以2为先,21653748
深度优先:以3为先,34762158 以2为先,21563478
最小生成树
连通图生成树:包含图中全部点,最少边,保持连通
最小生成树:带权值,边权值最小,图形不唯一
,但最小代价唯一
Prim算法(普里姆)
贪心算法
先选最小权值的边,再从以选中的顶点所附带的边中选择最小权值的边,以此类推,推出树图
Kruskal算法(克鲁斯卡尔)
贪心算法
每次选择一条权值最小的边,这条边两头连通(原本连通的就不选)
排序(需要代码)
交换排序
冒泡:把最大的或最小的冒到一边
每两个数字相互比较,按对应顺序排序,比较完一次,再和后面的一个数比较,以此类推
选择排序
类似打扑克牌时整理牌的顺序一样,从左往右整理
插入排序
折半查找
只能在顺序存储,不能在链表,元素有序
简答题备考
C语言
机器语言:紧密依赖于计算机的硬件
高级语言:比较接近人们习惯使用的自然语言和数学语言
程序:一组计算机能识别和执行的指令
源程序:用高级语言编写的程序
常量:程序运行过程中不能改变的量
变量:程序运行过程中其值可以改变的量
变量名:以一个容易记忆的名字代表存储单元的地址
转义字符:将反斜杠 “\” 后面的字符转换成另外的意义,输出信息时的控制符号 如 '\n’代表换行
字符串常量:一对双撇号括起来的字符序列
算术表达式:用算术运算符和括号将运算对象连接起来的、符合C语法规则的式子
数据结构:在程序中指定数据类型和数据的组织形式
算法:即操作步骤
修饰符:用来丰富格式字符功能的附加字符
关系表达式:用关系运算符将两个表达式连接起来的式子
逻辑表达式:用逻辑运算符将两个表达式连接起来的式子
用选择机构来检查所指定的条件是否满足,并根据判断的结果决定执行哪种操作
循环结构就是用来处理需要重复处理的问题
数组:具有相同类型的变量,用连续空间存储起来
字符数组:用来存放字符数据的数组
函数就是用来完成一定的功能的
函数的声明称为函数原型
递归调用:在调用一个函数的过程中又出现直接或间接地调用函数本身
局部变量:在函数或复合语句中定义的变量,只在本函数或复合语句内范围内有效
全局变量:在函数之外定义的变量,从定义变量到本源程序文件结束有效,在范围内可以为本程序文件中所有函数共用
静态存储:在程序运行期间由系统在静态存储区分配存储空间的方式,在程序运行期间不释放
动态存储:在函数调用期间根据需要在动态存储分配存储空间的方式
寄存器变量(register):一些变量频繁使用,将局部变量的值放在CPU中的寄存器,寄存器对于存取速度远高于内存的存取速度,这样可以提高执行效率
内部函数(静态函数):用static声明的,函数作用只局限于所在文件,其他文件不能引用
外部函数:函数首部最左端添加extern,可供其他文件调用
函数的定义:对函数功能的确立,包括指定函数名、函数值类型、形参及其类型以及函数体等,它是一个完整的、独立的函数单位
函数的声明:好吧函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查
变量的定义:定义变量时,要指明数据类型,编译系统要据此给变量分配存储空间,称为定义行声明
变量的声明:不必指定数据类型,数据类型在定义时指定了,只是为了引用的需要,称为引用性声明
将地址形象化地称为“指针”
指针变量:一个变量专门用来存放另一个变量的地址
结构体:用户自己建立由不同类型的数据组成的组合型的数据结构
结构体数组:一个结构体变量中可以存放一组有关联的数据
结构体指针:指向结构
枚举:将变量的值一一列举出来,变量的值只限于列举出来的值的范围内
程序文件:包括源程序(后缀为.c)、目标文件(后缀.obj)、可执行文件(后缀为.exe)文件等。这种文件是用来存放程序的,以便实现程序的功能
数据文件:文件内容不是程序,而是供程序运行时读写的数据,或共程序运行时读入内存的数据
文件分类:按数据的组织形式,数据文件可分为ASCII文件
和二进制文件
数据结构
数据:客观事物的符号表示,是所有能输入计算机中并被计算机程序处理的符号的总称
数据元素:是数据的基本单位,在计算机中通常作为一个整体进行考虑
数据项:组成数据元素的、有独立含义的、不可分割的最小单位
数据对象:是性质相同的数据元素的集合,是数据的一个子集
数据结构:相互之间存在一种或多种特定关系的数据元素的集合
算法:为了解决某类问题而规定的一个有限长的操作序列
算法特性:有穷性、确定性、可行性、输入、输出
算法基本标准:正确性、可读性、健壮性、高效性
线性表:由n个数据特性相同的元素构成的有限序列
如学生基本信息表,每个学生为一个数据元素,包括学号、姓名、性别、籍贯等数据项
节点:存储七本身的信息之外,还需存储一个指示七直接后继的信息,这两部分信息组成数据元素的存储映像
数据域:存储数据元素信息的域
指针域:存储直接后继存储位置的域
链表:n个节点链接成的表
栈:限定仅在表尾进行插入或删除操作的线性表
栈底:表头端
栈顶:表尾端
队列:一种先进先出的线性表
队尾:允许插入的一端
对头:允许删除的一端
栈和队列都有:顺序和链式存储
串也称为字符串,在 C 语言中是由数字、字母、下划线以及特殊字符组成的串字符,字符串需要用一对双引号括起来。在一个字符串中取一部分作为一个新字符串,这个新字符串叫子串,另一个叫做它的母串
树:n个节点的有限集
森林:n棵互不相交的树的集合
图(G):由两个集合V和E组成,记为G = (V,E),V是顶点的有穷非空集合,E是V中顶点偶对的有穷集合,这些顶点偶对 称为 边
查找表:由同一个类型的数据元素构成的集合
关键字:数据元素中某个数据项的值,用它可以标识一个数据元素
主关键字:此关键字可以唯一地标识一个记录
次关键字:用以识别若干记录的关键字
查找:指根据给定的某个值,在查找表中确定一个关键字等于给定值的记录或数据元素,如果存在查找成功,不存在查找失败
查找分类:顺序查找、折半查找、分块查找
排序:按关键字的非递减或非递增顺序对一组记录重新进行排列的操作