数据结构定义:
我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能而执行的相应的操作(比如查找某个元祖,删除某个元素,对某个元素进行排序),这个相应的操作也叫作算法。
数据结构 = 个体 + 个体的关系
算法定义:
结题的方法和步骤
算法 = 对存储结构的操作(狭义定义)
衡量算法的标准
1 时间的复杂度:大概程序要执行的次数,而非执行的时间(因为运行机器不同,执行时间不同)。
2 空间复杂度:算法执行过程中大概所占用的最大内存。
3 难易程度 (易读易懂)。
4 健壮性(可以理解成抗非法数据的能力)。
数据结构的地位:
数据结构是软件中最核心的课程。
程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言
预备知识
指针
指针的重要性:
指针
指针的重要性
表示一些复杂的数据结构
快速的传送数据
使函数返回一个以上的值
能否直接访问硬件
能够方便的使用数组和字符串
是理解面向对象语言中引用的基础
指针是C语言的灵魂。
定义
地址
内存单元的编号。
从0开始的非负整数
范围:0--FFFFFFFF【0--4G-1】
指针:
指针就是地址 地址就是指针
指针变量就是存放内存单元地址的变量
指针的本质是一个操作受限的非负整数。
分类
1.基本类型的指针。
int i=10;
int *p = &i;//等价于int *p; p=&i;
详解这两部分操作:
1)、p存放了i的地址,所以我们说p指向了i
2)、p和i是完全不同的两个变量,修改其中的任意一个变量的值,不会影响另一变量的值
3)、p指向i,*p就是i变量本身。更形象的说所有出现*p的地方都可以换成i,所有出现i 的地方都可以换成*p
int *p;//p是个指针变量,int *表示该p变量只能储存int类型变量的地址。
int i = 10;
p = &i;
//p = 10;error;
总结: 1、 如何一个指针变量(假定为p)存放了某个普通变量(假定为i)的地址,
那我们就可以说:“p指向了i”, 但p与i是两个不同的变量,
修改p的值不影响i的值,修改i的值不影响p的值.
2、 *p等价于i 或者说*p可以与i在任何地方互换
3、 如果一个指针变量指向了某个普通变量,则
*指针变量 就完全等价于 该普通变量
注意:
指针变量也是变量,只不过它存放的不能是内存单元的内容,只能存放内存单元的地址
普通变量前不能加*
常量和表达式前不能加&
#include
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、指针和数组
指针 和 一维数组
数组名
一维数组名是个指针常量,
它存放的是一维数组第一个元素的地址,
它的值不能被改变
一维数组名指向的是数组的第一个元素
下标和指针的关系
a[i] <<==>> *(a+i)
假设指针变量的名字为p
则p+i的值是p+i*(p所指向的变量所占的字节数)
指针变量的运算
指针变量不能相加,不能相乘,不能相除
如果两指针变量属于同一数组,则可以相减
指针变量可以加减一整数,前提是最终结果不能超过指针允许指向的范围
p+i的值是p+i*(p所指向的变量所占的字节数)
p-i的值是p-i*(p所指向的变量所占的字节数)
p++ <==> p+1
p-- <==> p-1
举例
如何通过被调函数修改主调函数中一维数组的内容【如何界定一维数组】
两个参数
存放数组首元素的指针变量
存放数组元素长度的整型变量
#include <stdio.h>
int main()
{
double *p;
double x = 66.6;
p = &x;//x占8个字节 1个字节是八位,一个字节一个地址
double arr[3] = {1.1,2.2,3.3};
double *q;
q = &arr[0];
printf("%p\n",q); //%p实际就是以16进制输出
q = &arr[1];
printf("%p\n",q);
}
动态内存分配和释放:
动态构造一维数组
假设动态构造一个int型数组
int *p = (int *)malloc(int len);
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. 1+2+3+4+.....+100
2. 求阶乘
3. 汉若塔
4. 走迷宫
模块二:非线性结构数 图
模块三:查找和排序
折半查找
排序:冒泡 插入 选择 快速排序 归并排序
Java中容器和数据结构相关知识