概念
数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等
的学科
数据(Data) :是客观事物的符号表示。在计算机科学中指的是所有能输入到计算机中并被计算机程序处理的符号的总称。
数据元素(Data Element):是数据的基本单位,在程序中通常作为一个整体来进行考虑和处理。
一个数据元素可由若干个数据项(Data Item)组成。数据项是数据的不可分割的最小单位。
数据对象(Data Object):是性质相同的数据元素的集合,是数据的一个子集。
数据结构(Data Structure):是指相互之间存在一种或多种特定关系的数据元素的集合。
存储结构:数据结构在计算机中的映射。包括数据元素的表示与关系的表示。
数据类型:分为值集、操作集
抽象数据类型:一个数据模型以及定义在改模型上的一组操作,数据对象,S是关系集,P是基本操作集。
头指针:链表中 第一个结点的存储位置(位置信息数据)
结点:包含存储数据元素信息的域(数据域)、存储直接后继存储位置的域(指针域)
头结点:单链前的第一个结点前附设一个结点,其指向第一个结点的信息
逻辑结构:集合结构、线性结构、树形结构、图形结构
物理结构: 顺序存储结构、链式存储结构
算法性质:
- 输入、输出
- 无穷性
- 确定性
- 可行性
算法要求:
- 正确性
- 可读性
- 健壮性(当输入不合理时,算法可以做出一些处理)
- 时间效率高和存储量低
影响算法的因素:
- 时间
- 空间
- 算法复杂度
时间复杂度: T(n)=O(1)<O(logn)<n<nlogn<n2<2n<n!<n^n
线性表与链表
C语言
头标识
#include<stdio.h>//头文件 //定义:输入输出语句;定义NULL=0与空;
字符串:
“A”=‘A’+’\0’
指针:
int *a,b;//a是指针,b是非指针 a=&b;//赋地址 *a=b;//赋值
C语言lnk2001一般是标准词出错
类与对象
typedef struct (S){
int data;int *next }S;S s//定义一个类名,typedef用于新建数据类型(例int),加struct定义其位类,无struct则是类的一个对象 struct S{
int data;int *next; }s; //定义一个对象名 main(){ int *p=(int *)malloc(sizeof(int)));//申请空间 (S s;)s->data=10;s->next=p;//赋值 free(p);//释放空间 }
顺式线性表
typedef struct{
int *elem;//存储首空间基地址 int length;//当前长度 int listsize;//当前分配容量 }SqList; L.elem=(int *)malloc((30+add)*sizeof(int));//申请空间
- 在等概率下,删除一个元素平均需要移动的元素数为(n-1)/2。
- elem[]是数组
链式线性表
typedef struct LNode{
int data; struct LNode *next; }LNode,*LinkList; //插入 s=(LinkList)malloc(sizeof(LNode)); //结点申请空间 s->data=e;s->next=p-next;p-next=s;
- 结点:数据域、指针域
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZyCdTa6-45)(F:\TyporaWorkplace\文件\图片\队列.PNG)]
顺式栈
typedef struct {
int *base; int *top; //top指的栈的最上位+1 int stacksize; }SqStack;SqStack s; stack.top=stack.base;//初始化栈 s.base=(int *)realloc(S.base,(stacksize+add)*sizeof(int));//增加空间 *s.top++=e;//入栈push e=*--s.top;//出栈pop e=*(s.top-1);//得顶值
栈的应用:判断表达式中的括号是否匹配,判断一个字符串是否是回文(即中心对称),程序执行过程中的嵌套调用和返回、函数的递归执行等。
链式队列
typedef struct LNode{
int data; struct LNode *next; }QNode; typedef struct{
QNode *front; QNode *rear; }LinkQueue; Q.rear=Q.front;//初始化队列 p->data=e;p->next=Null;Q.rear->next=p;Q.rear=p;//插入结点 e=Q.front->next->data;Q.front->next=Q.front->next->next;//删除头结点
数组与广义表
对称矩阵:aij=aji
稀疏矩阵:假设在一个n、m的矩阵中,有t个非零元素,设 δ=t/(n´m),称δ为稀疏因子,通常认为δ≦0.05
转置算法:
for(col=1; col<=nu ;++col) for(row=0 ; row<=mu ;++row) t[col][row]=m[row][col] ;
广义表D=((),(e),(3,2)
树
树概念
树的度为2
结点的度:结点的分支数
终端结点(叶子): 度为0的结点
树的度:树中所有结点度的最大值。
二叉树概念
- 二叉树的第 i 层上至多有pow(2,i-1)个结点
- 对任何一棵二叉树,若其叶子结点数为n0,度为2的结点数为n2,则n0=n2+1
满二叉树一棵深度为k且有2k-1个结点的二叉树
完全二叉树:编号从1到n的结点一一对应
遍历二叉树
- 前序遍历:(从根节点开始)先访问根节点,在遍历左子树,再遍历右子树
- 中序遍历:(从末端开始)从根节点开始,先访问左子树,再根节点,最后右子树
- 后序遍历:(从末端开始)从左到右先叶子后结点的方式遍历访问左右子树,最后根节点
- 层序遍历:从根开始,一层一层,从左开始,一个一个
森林与二叉树的转换
森林转化二叉
- 在树中,所有兄弟结点之间加一根连线
- 对每个节点,除了保留与其的长子的连线外,去掉该节点与其他孩子的连线
二叉转化森林
- 若结点x是其双亲y的左孩子,则把x的右孩子,右孩子的右孩子,~,都与y连起来
- 去除双亲到右孩子的连线
霍夫曼树(最优二叉树)
带权路径最短的树最短:该叶子权值*该叶子总路径数相加
例:5,29,7,8,14,23,3,11:形成二叉树
带权的路径长度为:WPL=(23+29)*2+(11+14)*3+(3+5+7+8)*4=271
树与森林的遍历
树的先根遍历——二叉树的先序遍历
后根遍历——二叉树的中序遍历
森林的先序和中序遍历即为其对应的二叉树的先序和中序遍历。
图
完全图 若有n个顶点的无向图有 n(n-1)/2 条边, 则此图为完全无向图。有n个顶点的有向图有n(*n-*1) 条边, 则此图为完全有向图。
连通图:无向图,vi和vj都是连通的
强连通图:都有以vi到vj 和从vj到vi都存在路径,称图G是强连通图
邻接矩阵
1是代表有边
遍历
深度优先——先根遍历
广度优先——层次遍历
克鲁斯卡尔算法
图对应的最小生成树算法
拓扑排序
AOV网:点+边+权值
拓扑排序:AOV网+箭头
关键路径
最早时间(正序)=最晚时间(逆序),的点
即最早时间(由A-B在满足,在各项条件下,路程最短)的路径
查找
顺序表查找
挨个查找
二分法查找(折半查找)
索引查找
把顺序表分成快,保证前面快一定大于后面快,索引表记录快的范围 在快内查找
多路查找树(查找二叉树)
- 2-3树((要求)所有叶子在同一个层次上)
- B树
哈希表(散列表)
散列表存储时按照算法存储
存储算法
- 直接定址法(H(key)=a·key+b(a,b为常数))
- 数字分析法对关键字进行分析,取关键字的若干位或组合作为哈希地址
- 平方取中法将关键字平方后取中间几位作为哈希地址
- 折叠法将关键字分割成位数相同的几部分,然后取这几部分的叠加和作为哈希地址
- 除留余数法
- 随机数法取关键字的随机函数值作哈希地址
冲突处理算法
- 开放定址法
- 再散列函数法
- 链地址法
- 公共溢出区法
排序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwS1bUls-46)(F:\TyporaWorkplace\文件\图片\排序.PNG)]
拓扑排序
有向图表明先后关系
一个有向图构造拓扑序列的过程
直接选择排序
直接从待排序数组里选择一个最小(或最大)的数字,每次都拿一个最小数字出来,顺序放入新数组,直到全部拿完;
堆排序
大顶堆:父比所有大 小丁堆:所有数都比父大,排出前几或后几
直接插入排序
对比所有找到比自己都大的,插入她的前面
希尔shell排序
分别(余数为4/3/2或为奇、为偶)交叉两两对比大小,若大于则交换,最后在进行单个直接插入排序
冒泡排序
Void bubble_sort(int a[],int n){
for (i=n-1,change=True; i≥1 && change; --i){
change=false; for (j=0; j<i; ++j) if (a[j]>a[j+1]) {
a[j] ←→a[j+1] ;change=True ; } } }
快速排序
分治法
设置枢轴记录(基准)通过一趟扫描将要排序的数据分割成独立的两部分,左右分别对比,直至左边的小于基准,右边的大于基准,循环使用此方法
归并排序
把原始数组分成若干子数组,对每一个子数组进行排序,继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组
基数排序
(以单链表)分别进行个位、十位、百位排序,逐渐生成
算法设计
分治法
将问题拆分成几个小的问题,用相同的方法递归性解决问题
贪心法
不为整体考虑,只选择当前的最好选择,可以快速得到短时间最满意的结果
回溯法
执行时碰到不能执行的,返回上一步继续执行,碰到多个解也要回溯
动态规划
原问题分成多个子问题,将子问题结果用表存起来,总问题通过表内得出结果。与分治法区别:需要用到查表