数据结构
一、基本概念
什么是数据结构
数据对象在计算机的组织方式
(逻辑结构 物理存储结构)
数据对象必定与一系列加在其上的操作相关联
完成这些操作所需要的方法就叫算法
递归
clocks()函数
抽象数据类型
算法
算法的概念
好算法的评定标准
时间复杂度
根据算法写成的程序执行时耗费时间的长度
空间复杂度
根据算法写成的程序执行时占用存储单元的长度
在分析一般算法的效率时,我们经常关注下面的两种复杂度
1.最坏情况复杂度
2.平均复杂度
复杂度的渐进表示法 ???
时间复杂度T(n),上界O(n),下界Ω(n)。
最小上界,最大下界???
应用实例
最大子列
算法一
算法二
算法三:分而治之
算法四:在线处理
二、线性结构
多项式的表示
如何表示多项式?
多项式的关键数据:
多项式项数n
各项系数ai和指数i
方法一:顺序存储的直接表示
数组各分量对应多项式各项:
a[i]:项xi的系数ai
方法二:顺序存储结构表示非零项
每个非零项aixi涉及两个信息:系数ai和指数i
可以将一个多项式看成是一个(ai,i)二元组的集合
用结构数组表示:数组分量是由系数ai,指数i组成的结构,对应一个非零项
方法三:链表结构存储非零项
链表中每个结点存储多项式一个非零项,包括系数和指数两个数据域以及一个指针域。
什么是线性表
线性表(Linear List) :由同类型数据元素构成的有序序列的线性结构
1.表中元素个数称为线性表的长度
2.线性表没有元素时,称为空表
3.表起始位置称表头,表结束位置称表尾
线性表的抽象数据类型描述
数据对象集
操作集
1.初始化(建立 一个空的线性表)
2.查找(返回线性表中第i个元素的值或地址)
3.插入(在第i个位置插入一个值为X的新元素)
4. 删除(删除表中第i个位置上的元素)
线性表的链式存储实现
不要求逻辑上相邻的两个元素物理上也相邻;通过“链”建立起数据元素之间的逻辑关系。
1.求表长 链表遍历
2.查找 按序号查找或按值查找
3.插入
4.删除 找到i-1个结点,指向删除结点,修改指针,删除结点,释放所指结点的空间。
广义表
广义表是线性表的推广
对于线性表而言,n个元素都是基本的元素
广义表中,这些元素不仅可以是单元素也可以是另外一个广义表
多重链表
链表中的节点可能属于多个链
多重链表中节点的指针域会有多个,如前面例子包含了next和sublist两个指针域;
但包含两个指针域的链表不一定是多重链表,比如双向链表不是多重链表。
多重链表有广泛的用途:
基本上如树,图这样相对复杂的数据结构都可以采用多重链表的方式实现存储。
矩阵可以用二维数组表示,但二维数组表示有两个缺陷:
一是数组的大小需要事先确定,
其次对于稀疏矩阵将造成大量的存储空间浪费。
十字链表
对于稀疏矩阵,采用一种典型的多重链表–十字链表来存储
只存储矩阵的非零元素项
每个节点通过两个指针域,把同行,同列串起来;
用一个标识域Tag来区分头节点和非零元素节点;
头节点的标识值为Head,矩阵非零元素节点的标识值为Term
堆栈
什么是堆栈?
问题导入:计算机如何进行表达式求值?
算数表达式由两类对象构成:
运算数,如2.3.4
运算符号,如+、-、*、/
不同运算符优先级不一样
前缀表达式:运算符号位于两个运算符之前,如+a * bc-/de
中缀表达式:运算符号位于两个运算数之间,如a+b * c-d/e
后缀表达式:运算符号位于两个运算数之后,如abc * +de/-
堆栈:具有一定操作约束的线性表
只在一端做插入,删除
插入数据:入栈
删除数据:出栈
后入先出:Last In First Out(LIFO)
堆栈的抽象数据类型描述
类型名称:堆栈
数据对象集:一个有0个或多个元素的有穷线性表
操作集:长度为MaxSize的堆栈S属于Stack,堆栈元素item属于ElementType
1.生成空堆栈,其最大长度为MaxSize
2.判断堆栈S是否已满
3.将元素item压入堆栈
4.判断堆栈S是否为空
5.删除并返回栈顶元素
栈的顺序存储实现
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成。
堆栈的链式存储实现
栈的 链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行。
中缀表达式如何转换为后缀表达式
从头到尾读取中缀表达式的每个对象,对不同对象按不同情况处理。
1.运算数:直接输出
2.左括号:压入堆栈
3.又括号:将堆栈的运算符弹出并输出,直到遇到左括号(出栈,不输出)
4.运算符:
若优先级大于栈顶运算符,则把它压栈
若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈
5.若各对象处理完毕,则把堆栈中存留的运算符一并输出。
堆栈的其他应用
函数调用及递归实现
深度优先搜索
回溯算法
队列及实现
什么是队列
队列:具有一定操作约束的线性表
插入和删除操作:只能在一端插入,而在另一端删除
队列的抽象数据类型描述
类型名称:队列
数据对象集:一个有零个或多个元素的有穷线性表
操作集:长度为MaxSize的队列Q属于Queue,队列元素item属于ElementType
1.生成长度为MaxSize的空队列
2.判断队列是否已满
3.将数据元素item插入队列Q中
4.判断队列Q是否为空
5.将队头数据元素从队列中删除并返回。
队列的顺序存储实现
队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成。
#define MaxSize<储存数据元素的最大个数>
struct QNode{
ElementType Data[MaxSize];
int rear;
int front;
};
typedef struct QNode *Queue;
入队列
void AddQ(Queue PtrQ,ElementType item)
{
if((PtrQ->rear+1)%MaxSize == PtrQ->front){
printf("队列满");
return;
}
PtrQ->rear = (PtrQ->rear+1)%MaxSize;
PtrQ->Data[PtrQ->rear] = item;
}
出队列
ElementType DeleteQ(Queue PtrQ)
{
if(PtrQ->front == PtrQ->rear){
printf("队列空");
return ERROR;
} else {
PtrQ->front = (PtrQ->front+1)%MaxSize;
return PtrQ->Data[PtrQ->front];
}
}
队列的链式储存实现
队列的链式存储结构也可以用一个单链表来实现。插入和删除操作分别在链表的两头进行;
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{ /*链队列结构*/
struct Node *rear; /*指向队尾节点*/
struct Node *front; /*指向队头节点*/
};
typedef struct QNode *Queue;
Queue PtrQ;
顺环队列
多项式加法运算
采用不带头节点的单向链表,按照指数递减的顺序排列各项
struct PolyNode{
int coef; //系数
int expon; //指数
struct PolyNode *link; //指向下一个节点的指针
};
typedef struct PolyNode *Polynomial;
Polynmial P1,P2;
算法 思路:
两个指针P1和P2分别指向这两个多项式第一个节点,不断循环;
比较指数是否相等,若相等,系数相加,若结果不为零,则作为结果多项式对应项的系数。同时,P1和P2都分别指向下一项;
若不想等,则将大的那一项存入结果多项式,并使该项指向下一项。