数据结构的基本概念
1、数据结构在学什么?
如何用程序代码把现实世界的问题信息化。
如何用计算机高效地处理这些信息从而创造价值。
2、数据是信息的载体,是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。
3、数据元素 是数据的基本单位,通常作为一个整体进行考虑和处理。一个数据元素可由若干数据项组成,数据项是构成数据元素的不可分割的最小单位。
4、数据结构是相互之间存在一种或多种特定关系的数据元素的集合。
5、数据对象是具有相同性质的数据元素的集合,是数据的一个子集。
6、数据结构的三要素?
逻辑结构:(集合结构 :各个元素同属一个集合,别无其他关系、线性结构 :数据元素之间是一对一的关系。除了第一个元素,所有元素都有唯一前驱;除了最后一个元素,所有元素都有唯一后继、树形结构 :数据元素之间是一对多的关系、图状结构:数据元素之间是一对多的关系)
数据的运算:针对某种逻辑结构,结合实际需求,定义基本运算
物理结构/存储结构(顺序存储 :把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中 ,元素之间的关系由存储单元的邻接关系来体现、链式存储 :逻辑上相邻的元素在物理位置上可以不相邻,借助指示元素存储地址的指针来表示元素之间的逻辑关系、索引存储 :在存储元素信息的同时,还建立附加的索引表。索引表中的每项称为索引项,索引项的一般形式是(关键字,地址)、散列存储 :根据元素的关键字直接计算出该元素的存储地址,又称哈希(Hash)存储):如何用计算机表示数据元素的逻辑关系?
7、存储结构的影响?
若采用顺序存储,则各个数据元素在物理上必须是连续的;若采用非顺序存储,则各个数据元素在物理上可以是离散的;
数据的存储结构会影响存储空间分配的方便程度;
数据的存储结构会影响对数据运算的速度;
8、运算的定义是针对逻辑结构的,指出运算的功能;
运算的实现是针对存储结构的,指出运算的具体操作步骤;
9、数据类型是一个值的集合和定义在此集合上的一组操作的总称。(原子类型:其值不可再分的数据类型、结构类型:其值可以再分解为若干成分(分量)的数据类型)
10、抽象数据类型(ADT)是抽象数据组织及与之相关的操作。
算法的基本概念
1、程序 = 数据结构 + 算法
2、算法是对特定问题求解步骤的一种描述,他是指令的有限序列,表示一个或多个操作。
3、算法的特性?
有穷性:一个算法必须总在执行有穷步之后结束,且每一步都可在有穷时间内完成。
确定性:算法中每条指令必须有确切的含义,对于相同的输入只能得出相同的输出。
可行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。
输入:一个算法有零个或多个输入,这些输入取自于某个特定的对象的集合。
输出:一个算法有一个或多个输出,这些输出是与输入有着某种特定关系的量。
4、"好"算法的特质?
正确性:算法应能够正确地解决求解问题
可读性:算法应具有良好的可读性,以帮助人们理解
健壮性:输入非法数据时,算法能适当地做出反应或进行处理,而不会产生莫名奇妙地输出结果。
高效率与低存储量需求。
5、如何计算算法的时间复杂度?
找到一个基本操作(最深层循环),分析该基本操作的执行次数x与问题规模n的关系x=f(n),x的数量级O(x)就是算法时间复杂度T(n)
6、常用技巧(时间复杂度和空间复杂度一样)?
加法规则:O(f(n)) + O(g(n)) = O(max(f(n), g(n)))
乘法规则:O(f(n)) * O(g(n)) = O((f(n) * g(n))
O(1) --- 常数复杂度 < O(log n) --- 对数复杂度 < O(n) --- 线性复杂度 < O(n log n) --- 对数线性复杂度 < O(nᵏ) --- 多项式复杂度 < O(kⁿ) --- 指数复杂度 < O(n!) --- 阶乘复杂度
7、三种复杂度:最坏、平均、最好时间复杂度
8、如何计算算法的空间复杂度?
普通程序:找到所占空间大小与问题规模相关的变量,分析所占空间 x 与问题规模 n 的关系 x = f(n),x 的数量级 O(x) 就是算法空间复杂度 S(n)
递归程序:找到递归调用的深度 x 与问题规模 n 的关系 x = f(n),x 的数量级 O(x) 就是算法空间复杂度 S(n)
线性表的基本概念
1、线性表是具有相同数据类型的 n(n>=0)个数据元素的有限序列,其中 n 为表长,当 n = 0 时线性表是一个空表。
2、线性表的基本操作
InitList(&L):初始化表。构造一个空的线性表L,分配内存空间。
DestroyList(&L):销毁操作。销毁线性表,并释放线性表L所占用的内存空间
ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。
ListDelete(&L,i,&e):删除操作。删除表L中第i个位置的元素,并用e返回删除元素的值。
LocateElem(L,e):按值查找操作。在表L中查找具有给定关键字值的元素
GetElem(L,i):按位查找操作。获取表L中第i个位置的元素的值。
其他常用操作:
Length(L):求表长。返回线性表L的长度,即L中数据元素的个数。
PrintList(L):输出操作。按前后顺序输出线性表L的所有元素值。
Empty(L):判空操作。若L为空表,则返回true,否则返回false。
顺序表
1、顺序表:用顺序存储的方式实现线性表
2、顺序表的实现 - 静态分配
cpp
#include <stdio.h>
#define MaxSize 10 //定义最大长度
typedef struct {
int data[MaxSize]; //用静态的"数组"存放数据元素
int length; //顺序表的当前长度
}SqList; //顺序表的类型定义(静态分配)
void InitList(SqList &L) {
for (int i = 0; i < MaxSize; i++) {
L.data[i] = 0; //将所有数据元素设置为默认初始值
}
L.length = 0; //顺序表初始长度为0
}
int main() {
SqList L;
InitList(L);
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
}
3、顺序表的实现 - 动态分配
cpp
#include <cstdlib>
#include <stdio.h>
#define InitSize 10 //默认的最大长度
typedef struct {
int *data; //指示动态分配数组的指针
int MaxSize; //顺序表的最大容量
int length; //顺序表的当前长度
}SeqList; //顺序表的类型定义(动态分配)
/// 初始化顺序表
/// @param L
void InitList(SeqList &L) {
// 用 malloc 申请一片连续的存储空间
L.data = (int *)malloc(InitSize * sizeof(int));
for (int i = 0; i < InitSize; i++) {
L.data[i] = 0;
}
L.MaxSize = InitSize;
L.length = 0;
}
/// 增加动态数组的长度
/// @param L
/// @param len
void IncreaseSize(SeqList &L, int len) {
int *p = L.data;
L.data = (int *)malloc((L.MaxSize + len) * sizeof(int));
L.MaxSize = L.MaxSize + len;
for (int i = 0; i < L.MaxSize; i++) {
L.data[i] = 0;
}
for (int i = 0; i < L.length; i++) {
L.data[i] = p[i];
}
free(p);
}
int main() {
SeqList L;
InitList(L);
for (int i = 0; i < 5; i++) {
printf("%d ", L.data[i]);
}
}