数据结构基础
定义:数据(数值或非数值)的逻辑结构,存储结构及其操作
数据
数据元素
计算机操作的是数据元素,包含多个数据项
用结构体数据类型进行封装
数据项
数据对象
多个数据元素的组合。类如一个学生表
逻辑结构
定义:数据对象与多个数据元素之间存在的特性。
分类:
集合
线性(1对1)
非线性(1对2,1对多,多对多)
存储结构
是数据对象存储在计算机,方便计算机操作,存储后的数据元素保留原有的逻辑结构
分类:
顺序存储:地址连续,大小相同,查找方便,增删数据不方便
链式存储:地址可以不连续,大小可以不相同,增删数据灵活
索引存储:存储空间是多段连续的,并且还附带索引表,检索速度快,但索引表占一定空间
哈希存储:又叫散列存储,由结点与关键码值决定存储位置,利用数据某一特性访问或存储,空间是连续的,访问速度快。
数据的操作(增删改查)
意义:提高写代码的效率,高效的完成程序
顺序表
1.顺序表的定义:
数据对象: data_type
typedef struct pepple{}
typedef int data_type
2.特点:
逻辑关系:1对1
存储结构:顺序存储
地址连续且大小相等,有索引,查找方便。
3.用数据类型封装
结构体
1.data_type arr[]
2.当前有效数据个数 int count
4.操作
1.表的创建
参数:无参
返回值:首地址
malloc一片连续的空间
2.数据的插入
参数:首地址; 插入位置; 插入数据元素
1.入参判断(空间是否存在,插入位置是否合法,表是否已满)
2.循环移动有效数据元素,从最后一个有效数据元素依次向右移动一个,移动到要插入的位置停止
3.将数据插入到当前位置
4.将有效数据个数(count)++
3.数据的删除
参数:首地址;删除位置;保存将要删除数据元素
1.入参判断(空间是否存在,表是否为空,删除位置是否合法)
2.将要删除的位置数据保存起来(*Data)
3.循环移动有效数据元素,从删除位置的下一位依次向左移动一位,到有效数据元素最后一位截至
4.将有效数据个数(count)--
4.数据的遍历
参数:首地址
从首地址开始,依次输出。
5.数据的销毁
参数:首地址
将首地址free并指向NULL
单链表
定义:将线性表中各元素分布在存储器的不同存储块,称为结点,通过地址指针建立它们的联系,所得到的存储结构。
特点:
逻辑结构:1对1
存储结构:链式
地址可以不连续,大小可以不固定,但逻辑上是连续的。查找不方便,没有索引,但增删方便。
用数据类型封装
结构体
数据域:data_type data
指针域:struct link *next
操作
1.表的创建
参数:无参
返回值:首地址
malloc块空间
2.数据的插入
1.参数:头地址;插入位置;插入数据元素
2.入参判断空间是否存在,插入位置是否合法,表是否已满)
3.创建一个新结点pNew
4.将要插入的元素内容放到新结点的数据域中
5.头部插入
先保护好要插入结点后的结点,再直接进行插入
6.尾部插入
1.定义一个游标pTemp并让头节点与之相等
2.循环让pTemp的next指向NULL截止
3.再将新结点直接插入
7.中间插入
1.定义一个游标pTemp并让它与头结点相等
2.循环让pTemp走到位置pos的上一个数据元素位置截止
3.保护好要插入结点之后的结点,再将新结点直接插入
3.数据的删除
1.参数:头地址;要删除的位置;要删除的数据
2.入参判断(空间是否存在,表是否为空,删除位置是否合法)
3.定义pTemp与pDel双游标,并将头地址赋给pTemp,将头节点的指向赋给pDel,让它变成首地址
4.头部删除
1.保存将要删除的位置元素内容
2.将首结点的指向赋给头结点
3.释放pDel并让它为NULL
5.尾部删除
1.给pDel赋给pTemp,并循环到pTemp指向NULL截止
2.保存将要删除位置的元素
3.释放pDel并让它指向NULL
6.中间删除
1.给pDel赋值pTemp,并循环到要删除位置的上一位元素地址截止
2.保存将要删除位置的元素
3.将pDel的指向赋给pTemp的指向
4.释放pDel并让它指向NULL
4.数据的遍历
1.参数:头地址
2.入参判断
2定义新右边pTemp,并让头结点的指向赋给ta
3.循环输出pTemp中的数据,并让它循环指向下一位数据元素,到指向NULL时截止
5.数据的销毁
1.参数:**pphead 头地址
2.入参判断
3.定义一个新游标pTemp,并让头地址的指向赋给pTemp
4.循环如果pTemp指向NULL则退出
5.如果首地址存在则循环将首地址pTemp的指向赋给头结点*ppHead的指向
6.循环释放pTemp,并循环让它指向NULL
双链表
操作
1.表的创建
2.数据的插入
1.参数:头地址;插入位置;插入数据元素
2.入参判断
3.申请一块空间pNew,并让要插入元素的数据保存到pNew的数据空间中
3定义一个游标pTemp并让头地址pDead赋给它
4.中间插入
1.循环移动pTemp到要插入位置的上一个数据元素地址截止(pos-1)
2.保存要插入结点后的结点,先修改pNew的指针域(pTemp的指向赋给pNew的指向,并且pTemp赋给pNew上一位pre)
3.判断pTemp的指向的下一位数据元素是否为空,如果是则让pTemp直接指向pNew,如果不是则让pTemp指向的下一位数据元素的上一位指针域(pre)指向pNew
1.头部插入
2.尾部插入
3.数据的删除
1.参数:头结点;要删除的位置;要删除位置的数据
2.入参判断
3.定义双游标pTemp与pDel,并让头结点赋给pTemp,让头结点的指向赋给pDel
4.判断如果pDel不为NULL,则让pDel赋给pTemp并循环移动到删除位置的上一个元素位置。如果pDel为NUll则返回退出
5.保存要删除元素的数据
6让删除元素的后一位与前一位建立联系。
7.释放要删除的结点pDel,并让它指向NULL
4.数据的遍历
1.参数:头结点
2.入参判断
3.建立游标pTemp,并让头结点的指向赋给它
4.如果pTemp不为空则让它循环输出pTemp中的数据,直到为null截止
栈
定义:栈是限制在一端进行插入或删除的顺序表,俗称堆栈。允许操作的一端称为栈顶,另一端称为栈底,没有元素时称空栈。
特点:
逻辑结构:1对1。一个元素接着一个元素存放
存储结构:有顺序存储,称顺序栈;有链式存储,称链式栈
先进后出(LIFO),只限定在栈顶操作
用数据类型封装
结构体
1.data_type arr[N]
2.int Top Top=-1为空;Top=N为满。
操作
1.栈的创建
2.入栈
1.参数:首地址;要插入的数据
2.入参判断(首地址是否存在;栈是否为满)
3.top自加
4.将数据保存到栈中(赋给top)
3.出栈
1.参数:首地址;要删除的数据
2.入参判断(首地址是否存在;栈是否为空)
3.要出栈的数据进行保存
4.top自减
4.栈的遍历
1.参数:首地址
2.入参判断
3.循环输出数据,直到小于top截止
队列
定义:类似顺序表,队头插入元素叫入队,队尾插入元素叫出队
特点:
逻辑结构:1对1
存储结构:顺序存储叫顺序队列,链式存储叫链式队列
先进先出
用数据类型封装
结构体
1.data_type arr[N]
2.int front 队头删除
3.int rear 队尾插入
操作
1.创建队列
1,参数:无参
2.在创建队列时就初始化队头与队尾为N-1
2.入队
1.参数:首地址;要入队的数据
2.入参判断(判断首地址是否存在;判断队列是否为满:(pQueue->rear+1)%N == pQueue->front)
3.rear保存向右自增后的新地址(pQueue->rear = (pQueue->rear+1)%N)
4.数据赋给rear
3.出队
1.参数:首地址;要删除的数据
2.入参判断(判断首地址是否存在;判断队列是否为空:(pQueue->rear== pQueue->front)
3.(pQueue->front = (pQueue->front+1)%N)
4.将要删除的元素保存起来
3.队的遍历
1.参数:首地址
2.入参判断
3.循环输出每个位置的数值,直到输出最后一位N位置截止
树
定义:n个结点的有限集合。满足两个条件:有且只有一个根结点;其余结点互不相交的有限集合,其中没一个集合称为根的子树。
树的结点分类
根结点:没有双亲,有孩子
中间结点:有双亲,有孩子
叶子结点: 有双亲,没孩子
森林:多个根,独立的互不相交的树的集合
树的概念
结点的度数:
一个结点的子树的个数称为该结点的度数;
A结点:B,C,D三个子树,A结点的度数,就是3
叶子结点:度数总是为0;
树的度数:
树中的各结点的度数的最大值。树的度数
层数:根结点的层数定义为第一层
树的深度:是树中结点层数的最大值为这颗树的深度;
逻辑结构:1对多
二叉树
定义:n个结点的有限集合,它或者是空集,或者由一个根节点以及两棵互不相交称为左子树和右子树的二叉树组成。二叉树与普通有序树不同,就算是一个子结点也要严格区分左孩子与有孩子。
逻辑结构:1对2
性质:
1.二叉树的第i层上至多有2^(i-1)个节点,其中i>=1
2.深度为k的二叉树中至多有2^(k)-1个节点。
3.度数为0的结点的个数:n0,字结点有0个
度数为1结点个数:n1,子结点有n1个
度数为2结点个数:n2,子结点有2*n2个
总结点:n=n0+n1+n2
总结:度数为0结点个数等于度数为2结点个数加一个 :n0=n2+1
满二叉树
1.只有度数为0或度数为2的结点的二叉树,切度数为0一定在最后一层
2.度数为k有2^k-1个结点个数
完全二叉树
对二叉树按层进行编号,如果编号与满二叉树编号位置完全一致但不是满二叉树则为完全二叉树
顺序存储
1.将不完全二叉树顺序存储首先要让它转化完全二叉树
2.将完全二叉树顺序存储,从左至右,根节点为1号位置
3.n个节点的完全二叉树用n+1元素的数组进行顺序存储,结点与数组下标一一对应,数组0下标不用。
二叉树的遍历
树中每个结点仅只访问一次,
线性结构遍历只有一条路径,非线性结构遍历二叉树有两个后继,因此路径不唯一。
三种遍历方式:
前序遍历:根左右
中序遍历:左根右
后序遍历:左右根
二叉树链式存储:给定一组树,取第一个数作为根,后面数依次与第一个数比较,大的放入右子树,小的放入左子树
用数据类型封装
结构体
struct treenode *lchild 左子树
struct treenode *rchild 右子树
date_type data 数据域
操作
1.创建树
1.参数:数据域
2.返回值:根节点首地址
3.申请完空间后直接将数据放入
2.数据的插入
参数:根结点 数据域
1.入参判断
2.创建新结点
3.将数据放入新节点数据域中
4循环判断新结点数据比根结点数据大还是小,大的放右子树,小的放左子树
5.判断左右子树是否为null,为null直接插入数据,不为null循环,指向null截止。
3.数据的遍历
前序遍历
1.参数:根节点地址
2.判断递归边界条件
3.先访问根节点数据元素再访问左子树数据元素再访问右子树数据元素
赫夫曼树(最优二叉树)
1.带权路径长度(pwl)最短的树
2.树的路径长度:从树根到每个节点的数据之和
3树的带权路径长度(wpl):所有叶子结点带权路径长度之和
赫夫曼编码:
赫夫曼树的生成: