学习教程为:【郝斌】-数据结构入门
指针
int * p;//int * 表示该p变量只能存储int类型变量的地址。如果变量a的类型是char,那么运行p = &a;就会报错
p=&i;//那么*p就表示i
int * p定义了一个形参,形参名字叫p,类型是int *
把i地址发给了p,p指向i,*p就是i,执行完i=100
a指向的元素有几个字节,那a+1指向的下一个也是几个字节
上图p里面只存放一个地址(第一个字节的 地址)
指针变量都只占四个字节,无论它指向的是几个字节的元素
无论什么类型的变量,想改他的值,发他的地址就行:(p已经是int *类型的了,要发p的地址就要用int**类型)
结构体
结构体是类的过渡,只能定义数据类型,内部不能有函数
malloc()动态分配内存
malloc只能返回第一个字节的地址,所以前面要加int *告诉编译器这个地址到底是整型的地址还是什么:
malloc动态分配内存需要手动释放内存。
模块一:线性结构
数组(连续存储)
上面show_arr可以写传入arr也可以写传入&arr,但是写arr的话要传入12个字节,因为arr里面有3x4个字节,而&arr就只会传入4个字节。
上面红框部分不应该用&pArr,因为pArr已经是struct Arr *类型的了(红框上一行定义了),如果再取地址就不是struct Arr *类型的,就不能传给黑色背景部分的pArr。
pBase是数组的首地址,pBase[i]是数组内容
链表(离散存储)
typedef用法
链表
插入结点
删除结点
c++ c要手动释放内存
代码实现
还要在前面补函数声明:
栈
动态分配的在堆里面分配(例如用malloc分配的,程序员手动分配),静态分配的在栈里面分配(例如函数内部的静态变量,系统分配)
pBottom指向最后一个结点的下一个结点,即头结点
pTop指向栈顶
算法示意图:
初始化:
造出一个空栈,pBottom和pTop都指向一个没有用的头结点
压栈:
初始化:
压栈:
遍历:
出栈pop:
清空
栈的应用
队列
front指向第一个元素,rear指向尾部,要删只能从front删,要加只能从rear加
循环队列
f指向第一个元素,r指向最后一个元素的下一个元素
添加元素时r越界了就循环到下面去:
参数含义
入队
%是取余
出队
判断循环队列是否为空
判断循环队列是否已满
队列的第一个元素:f,第二个元素(f+1)%队列长度。上图队列是qrsm
循环队列程序演示
队列的具体应用
递归
不同函数相互调用
自己调用自己
阶乘的循环使用
求n的阶乘,通过求n-1的阶乘获得
一个函数为什么可以自己调自己
模块二:非线性结构
树
图
模块三:查找和排序
排序
冒泡排序
法1.第1位依次跟第2、3、4等等到最后一位比大小,每次把小的那个放在第1位,这样第1位最后就是最小的
法2.第1位与第2位比,大的放第2位,第2位再与第3位比,大的还是放右边,依次进行,最后最大的数在最后一位。