数据结构
数据结构 = 个体的存储+个体关系的存储
算法=对存储数据的操作
程序=数据结构+算法
衡量算法的标准
时间复杂度:注意不是程序执行的时间,因为一个程序执行的时间取决于软硬件环境,不同的机器,执行的速度不一样,配置好的电脑自然而然速度块,所以时间复杂度是指的程序中的渐进时间复杂度,是指程序中基本语句(执行次数最多的语句)的幂级数(高数的求极限抓大头的思路e_e)
空间复杂度:算法执行过程中大概占用的辅助空间
难易程度:主要是应用方面看重
健壮性(鲁棒性):对于一些非法和意想不到的输入不能直接挂掉,肯定要有对应的措施反应非法输入
数据结构的特点
数据结构是一个程序的关键点,但感觉学了似乎啥也干不了e_e
内存中什么叫做栈?什么叫做堆?
并不是内存中专门分配一块区域叫栈,一块区域叫堆,其实只是分配内存的算法不一样,如果是以出栈压栈的方式为栈内存,如果是以堆排序的方式则为堆内存
程序=数据的存储+数据的操作+可以被程序执行的语言
预备知识
指针:指针是C语言的灵魂所在
地址:地址是内存单元的编号,从0开始的非负整数,范围取决于你的机器是多少位的机器,如果是32位的,则是0~0xFFFF_FFFF(4G-1)
指针:指针就是地址,地址就是指针
指针变量存放的是内存单元地址的变量,存的是一个地址
指针的本质是一个操作受限的非负整数
变量并不一定连续分配,随机分配内存
内存:内存是多字节组成的线性一维存储空间
内存的基本划分单位是字节
每个字节含有8位,每一位是二进制的0或者1
内存和编号是一一对应的,可以理解为内存地址就是一个门牌号,内存就是这个房间软件在运行前需要向操作系统申请存储空间。在软件运行期间,该软件所占空间不再分配给其他软件。当软件运行完毕后,操作系统将回收该内存空间(操作系统并不清空该内存空间中遗留下来的数据)。其实你用指针还能得到原来的数据,它释放只是回收了控制权
Note:
指针变量也是变量,只是一种特殊的变量类型,普通变量前面不能加*,常量和表达式前面不可以加&(&为取地址,*取值)
局部变量只能在本函数内部使用
如何通过被调函数修改主调函数中普通变量的值
实参为相关变量的地址
形参为以该变量类型的指针变量
在被调函数中通过 *形参变量名 的形式就可以修改实参的值,因为归根究底改变了实参地址里面的值,毫无疑问,实参会变化
传参有三种方式,C里面有传值和传地址(通过指针),C++有一种额外的引用传参(就是通过&参数)这里&参数和实参共用一个内存地址
所有的指针变量都是一个四字节的变量,因为地址是32位的四个字节
结构体
结构体:为什么会有结构体,为了表示一些复杂的数据,而普通的基本数据类型已经无法满足要求,就出现了构造数据类型,结构体是用户根据实际需要自己定义的复合数据类型, 自己定义的数据类型
如何使用结构体:
两种方式:
struct Student st = {1000,"zhangsan",21}; 通过结构体变量名来实现
struct Student *pst = &st; 通过指向结构体变量的指针来实现(强烈推荐)
跨函数使用内存
因为平常用到的内存是静态分配的,一些调用函数执行完之后,该函数的局部变量和内存就被释放了,其他函数无法访问,这里使用C语言的malloc动态内存分配函数,就可以在其他函数里使用到本函数通过malloc分配的内存
这里有一个和C++创建对象一样的思想:
A a = new A(); //A是一个类
A *pa = (A*)malloc(sizeof(A));
个人总结
这里学到了以前没有体会到的概念:
数据名就是一个指针常量,它是指向数组的第一个元素的地址
函数名其实也是一个指针常量,它指向函数的地址,函数指针就是这个思想
int a[10] = {1,2,3,4,5,6,7,8,9,10}
int *p = a
int *q =&a //虽然这里可以看到,&a和a其实都是指的数组的第一个元素,打印出来结果都是第一个元素的地址
//但是二者的偏移是不同的, p =(char *) a+1
尽管a 和&a的值是一样的,都是数组的首地址,但是类型不一样:
a作为地址是 int *类型的,
&a地址是int (*)[3]类型的,即一个数组指针,加1之后,是加整个数组的长度,即12。
图中的
int *q = &a + 1 等同于 int (*q)[5] = &a + 1