一、线性表及其实现
- 线性表(list):由同类型数据元素构成有序序列的线性结构
- 数据对象集:线性表是n(>=0)个元素构成的有序序列(a1,a2,……,an)
- 操作集:线性表L∈List,整数i表示位置,元素x∈ElementType,线性表基本操作主要有:
List MakeEmpty ()
//初始化一个空线性表
ElementType FindKth ( int K , List L)
//根据位序K,返回相应的元素
int Find (ElementType X , List L)
//在线性表L中,查找X第一次出现位置
void Insert (ElementType X , int i , List L)
//在位序i前面插入一个新元素x
void Delete (int i , List L)
//删除指定位序i的元素
int Length (List L)
//返回线性表L的长度n
- 顺序存储:利用数组的连续存储空间顺序存放线性表的各元素
- 链式存储:不要求逻辑上相邻的两个元素物理上也相邻,通过链建立起数据之间的逻辑关系
- 广义表:
① 是线性表的推广
② 对于线性表,n个元素都是基本单元素
③ 这些元素不仅可以是单元素也可以是另一个广义表
typedef struct GNode *GList;
struct GNode {
int Tag; //标志域:0表示是单元素,1表示是广义表
union{//子表指针域SubList与单元数据元素域Data复用
ElementType Data;
GList SubList;
}URegion;
GList Next; //指向后继节点
}
- 多重链表:链表中的节点可能同时隶属于多个链,多重链表中的结点的指针域会有多个,但包含了两个指针域的链表不一定是多重链表
二、堆栈(stack)
- 具有一定操作约束的线性表。
只在一端(栈顶,Top)做插入删除 - 插入数据:入栈(push)
删除数据:出栈(pop)
后入先出:Last in First Out(FIFO) - 一个有0个或多个元素的有穷线性表
- 操作集:长度为MaxSize的堆栈,s∈stack,堆栈元素item∈ElementType
Stack CreateStack(int MaxSize)
//生成空堆栈,最大长度为MaxSize
int IsFull(stack s,int MaxSize)
//判断堆栈是否已满
void Push(stack s,ElementType item)
//将元素item压入堆栈
int isEmpty(stack s)
//判断堆栈s是否为空
ElementType Pop(stack s)
//删除并返回栈顶元素
- 栈的顺序存储实现:栈的顺序存储结构通常由一个一维数组,和一个记录栈顶元素位置的变量组成
#define MaxSize //存储数据元素的最大个数
typedef struct SNode *stack;
struct SNode{
ElementType Data[MaxSize];
int Top;
};
- 堆栈的链式存储实现:实际上就是一个单链,叫做链栈,插入和删除操作只能在链栈的栈顶进行。
栈顶指针Top在链表的表头,便于插入和删除
typedef struct SNode *Stack;
struct SNode{
ElementType Data;
struct SNode *Next;
}
- 堆栈应用:表达式求值
运算数:入栈
运算符:从堆栈中弹出适量运算数,计算结果并入栈
堆栈顶上的元素就是表达式的结果值 - 中缀表达式转换为后缀表达式
从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。
运算数:直接输出
左括号:压入堆栈
右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)
运算符:①若优先级大于栈顶运算符时,则把它压栈;②若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;③再比较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈;
若各对象处理完毕,则把堆栈中存留的运算符一并输出。
三、队列(Queue)
- 具有一定操作约束的线性表,只能在一段插入,在另一端删除
- 数据插入:入队列(AddQ)
数据删除:出队列(DeleteQ)
先进先出:FIFO 先来先服务 - 数据对象集:一个有0个或者多个元素的线性表
- 操作集:长度为MaxSize的队列Q∈Queue,队列元素item∈ElementType
Queue CreatQueue( int MaxSize )
//生成长度为MaxSize的空队列
int IsFullQ( Queue Q, int MaxSize )
//判断队列Q是否已满
void AddQ( Queue Q, ElementType item )
//将数据元素item插入队列Q中;
int IsEmptyQ( Queue Q )
//判断队列Q是否为空;
ElementType DeleteQ( Queue Q )
//将队头数据元素从队列中删除并返回。
- 队列的顺序存储实现:队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成。
#define MaxSize //储存数据元素的最大个数
struct QNode {
ElementType Data[ MaxSize ];
int rear;
int front;
};
typedef struct QNode *Queue;
-
顺环队列:
队空时: rear=front
队满时: 也会出现rear=front,则无法判别队空还是满。
解决方案:①使用额外标记:size或tag。②仅使用n-1个数组空间 -
队列的链式存储的实现
队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行。
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{ /* 链队列结构 */
struct Node *rear; /* 指向队尾结点 */
struct Node *front; /* 指向队头结点 */
};
typedef struct QNode *Queue;
Queue PtrQ;