目录
数据结构概述
预备知识:
模块:
这篇笔记是根据郝斌老师的上课讲义整理而得:
数据结构概述
定义:如何把现实中大量复杂的问题以特定的数据类型和特定的存储结构保存到主存储器中(内存)中, 以及在此基础上为实现某一个功能而执行的相应操作,这个相应的操作也叫算法。
特定的数据类型和结构是指:如果我们保存少量的数据,我们可以使用数组(连续);如果保存大量的数据,我们就必须使用链表(不连续,通过指针相连);如果我们还要保存数据item之间的关系,如一个部门的上下级关系,我们就必须使用树来保存;如果我们要保存一个城市的地图(任何节点之间都可能产生关系),那我们必须使用图来保存。
数据结构 = 个体的存储+个体的关系存储
算法 = 对存储数据的操作
算法:
解题的方法和步骤
衡量算法的标准
1. 时间复杂度:大概程序要执行的次数,而非执行的时间
2. 空间复杂度:算法执行过程中大概所占用的最大内存
3. 难易程度
4. 健壮性
数据结构的地位:
数据结构是软件中最核心的课程
程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言
预备知识:
1)指针:
指针是C语言的灵魂 ;
表示一些复杂的数据结构 ;快速的传送数据;使函数返回一个以上的值;能直接访问硬件 ;能够方便的使用数组和字符串;是理解面向对象语言中引用的基础
定义:地址,内存单元的编号。指针变量占4个字节。指针就是地址 地址就是指针;指针变量是存放内存单元地址的变量;指针的本质是一个操作受限的非负整数
分类:
1. 基本类型的指针
int *i;
如何通过被调函数修改主调函数中普通变量的值
Ⅰ 实参为相关变量的地址
Ⅱ 形参为以该变量的类型为类型的指针变量Ⅲ在被调函数中通过 *形参变量名 的方式就可以修改主函数相关变量的值void f(int * p) //不是定义了一个名字叫做*p的形参, 而是定义了一个形参,该形参名字叫做p,它的类型是int *
{*p = 100; //
}int main(void)
{int i = 9;f(&i);printf("i = %d\n", i);return 0;
}
2. 指针和数组的关系
指针 和 一维数组
数组名
一维数组名是个指针常量,它存放的是一维数组第一个元素的地址, 它的值不能被改变一维数组名指向的是数组的第一个元素
int a[5] = {1,2,3,4,5};
printf("%p\n", *a+1);//平移四个字节地址double arr[3];
double *q;
q = &arr[0];
q = &arr[1]; //平移8个字节地址,但指针变量只占4个字节
void Show_Array(int * p, int len)
{int i = 0;for (i=0; i<len; ++i)printf("%d\n", p[i]);//p[2] = -1; //p[0] == *p p[2] == *(p+2) == *(a+2) == a[2]//p[i]就是主函数的a[i]
}int main(void)
{int a[5] = {1,2,3,4,5};Show_Array(a, 5); //a等价于&a[0], &a[0]本身就是int *类型//printf("%d\n", a[2]);return 0;
}
指针的指针
结构体:
为什么会出现结构体
为了表示一些复杂的数据,普通的数据类型无法满足要求
什么叫结构体
结构体是用户根据实际需要自己定义的复合数据类型
如何使用结构体
#include <string.h>struct Student
{ int sid;char name[200];int age;
}; //分号不能省int main()
{strcpy(st.name, "lisi");struct Student * pst = &st;pst->sid ==(*pst).sid == st.sid; //pst所指向的结构体变量中sid成员}
注意事项
结构体变量不能加减乘除,但可以相互赋值
普通结构体变量和结构体指针变量作为函数参数的问题
传输的时候最好传输指针:地址,而不要传输变量,因为变量可能需要传输很多字节,而指针始终传输的是四个字节。
动态内存的分配和释放
int * pArr = (int *)malloc(sizeof(int) * len);//等价于 int pArr[len]
*pArr = 4;//等价于a[0] = 4
pArr[1] = 10;//等价于a[1] = 10free(pArr);1、 malloc只有一个int型的形参,表示要求系统分配的字节数
2、 malloc函数的功能是请求系统len个字节的内存空间,如果请求分配成功,则返回第一个字节的地址,如果分配不成功,则返回NULL
3、 malloc函数能且只能返回第一个字节的地址,所以我们需要把这个无任何实际意义的第一个字节的地址(俗称干地址)转化为一个有实际意义的地址,因此malloc前面必须加(数据类型 *),表示把这个无实际意义的第一个字节的地址转化为相应类型的地址。如:
int *p = (int *)malloc(50); 表示将系统分配好的50个字节的第一个字节的地址转化为int *型的地址,更准确的说是把第一个字节的地址转化为四个字节的地址,这样p就指向了第一个的四个字节,p+1就指向了第2个的四个字节,p+i就指向了第i+1个的4个字节。p[0]就是第一个元素, p[i]就是第i+1个元素double *p = (double *)malloc(80);
表示将系统分配好的80个字节的第一个字节的地址转化为double *型的地址,更准确的说是把第一个字节的地址转化为8个字节的地址,这样p就指向了第一个的8个字节,p+1就指向了第2个的8个字节,p+i就指向了第i+1个的8个字节。p[0]就是第一个元素, p[i]就是第i+1个元素
free(p)
释放p所指向的内存,而不是释放p本身所占用的内存
模块:
模块一:线性结构
连续存储[数组]
离散存储[链表]
线性结构的两种常见应用之一 栈
线性结构的两种常见应用之二 队列
专题:递归
- 1+2+3+...+100
- 求阶乘
- 汉诺塔
- 走迷宫
模块二: 非线性结构
- 树
- 图
模块三: 查找和排序
折半查找
排序:
- 冒泡
- 快速排序
- 插入排序
- 选择排序
- 归并排序