线性数据结构
包含n个相同性质数据元素的有限子列。
- .
基本特征:
- 存在唯一的“第一个元素”
- 存在唯一的“最后一个元素”
- 除最后一个元素外,其他数据元素均有唯一的“直接后继”
- 除第一个元素外,其他数据元素均有唯一的“直接前驱”
- 前后关系是“一对一关系”,即线性关系。
典型线性数据结构
- 栈 : 只允许在末端进行操作
- 队列 :只运行在两端进行操作
- 线性表 :允许在序列任意位置进行操作
栈
- 对于栈来说,最后一个元素所在端具有特殊意义,称为栈顶;第一个元素称为栈底;不含任何元素的栈称为空栈。
数据结构和算法(线性数据结构)线性数据结构 - 栈的插入操作是将新的元素插入栈顶,称为入栈,或压栈。
- 栈的删除操作时删除栈顶的元素,称为出栈,或弹栈。
- 栈的操作是按先进后出的操作原则进行的,故栈又称为先进后出的线性数据结构。
- 栈的常用操作为:入栈、出栈、取栈顶元素。
队列
- 通常将队列的插入操作称为入队,队列的删除操作称为出队,允许插入的一端称为对尾,允许删除的一端称为对头。不含任何元素的队列称为空队列。
- 队列遵循先进先出的原则,因此队列也称为先进先出的线性数据结构。
- 队列的常用操作:入队,出队,取队头元素等。
数据结构和算法(线性数据结构)线性数据结构
线性表
- 线性表的操作位置不受限制。线性表中所含数据元素的个数称为线性表的长度,长度为0的表称为空表。按元素升序或降序排列的线性表称为有序线性表,简称有序表。
- 线性表中数据元素可以是数、字符、也可以是其他复杂信息。
数据结构和算法(线性数据结构)线性数据结构
线性结构的存储表示
- 主要形式:顺序存储和链式存储
- 顺序存储的特点是借助数据元素在存储空间中的相对位置来表示元素之间的逻辑关系。最简单的一种方式是用相邻位置表示逻辑关系,即逻辑相邻的元素在物理上也相邻。
数据结构和算法(线性数据结构)线性数据结构
- 顺序存储的特点是借助数据元素在存储空间中的相对位置来表示元素之间的逻辑关系。最简单的一种方式是用相邻位置表示逻辑关系,即逻辑相邻的元素在物理上也相邻。
- 链式存储的特点是借助指示数据元素存储的地址指针表示元素之间的逻辑关系。
数据结构和算法(线性数据结构)线性数据结构 -
由于栈、队列、线性表具有不同的操作特点,在实际组织链表时,会采用不同的方式;
- 栈的操作只允许在栈顶进行,故将其链表的头指针作为栈顶指针,指向栈顶元素结点;
- 队列的操作只允许在队头和队尾两端进行,故将其链表的指针作为队头指针,指向对头元素结点,并增设队尾指针指向队尾元素结点;
- 线性表的操作位置不受限制,故其具有多种链表组织方式。
-
顺序存储
顺序栈
采用顺序结构的栈称为顺序栈,即需要用一片地址连续的空间来存储栈的元素。=>可用一个数组来实现,并指定栈顶元素位于序列末端,每当新元素入栈或出栈时,数组中其他元素可不改变位置,只需改变栈顶位置即可。=>由于c语言数组的大小是预先固定的,空间存满后,则不能继续插入新元素;因此,可以采用动态分配的一段连续的存储空间来储存栈的元素。
顺序栈的类型定义
typedef struct{
ElemType * elem; //存储空间的基址
int top; //栈顶元素的下一个位置,简称栈顶位标
int size; //当前分配的存储空间
int increment; //扩容时,增加的存储容量
}SqStack; //顺序栈
-
初始化顺序栈
将顺序栈S置为初始容量为size的空栈。算法复杂度O(1).
Status InitStack_Sq( SqStack &S, int size, int inc){
//分配存储空间
S.elem = (ElemType * )malloc(size * sizeof(ElemType));
if(NULL == S.elem)return OVERFLOW; //空间分配失败
S.top = 0; //置S为空栈
S.size = size; //初始容量值
S.increment = inc; //初始增量值
}
- 销毁顺序栈
Status DestoryStack_Sq(SeqStack &S)
{
S.size = 0;
S.increment = 0;
free(S->elem); //释放顺序栈分配的空间
}
- 判断顺序栈是否为空
Status StackEmpty_Sq(SqStack &S){
if(S.top == 0)return TRUE; //若栈顶位标为0,说明此时栈为空
else return FALSE;
}
- 清空栈S
Status ClearStack_Sq(SqStack &S){
if(S == NULL){
printf("顺序栈不存在!\n");
return;
}
S.top = 0; //将栈顶位标置为栈底,此时将栈为空栈
printf("顺序栈清空成功!\n");
}
- 元素压栈
数据结构和算法(线性数据结构)线性数据结构
Status Push_Sq(SqStack &S, ElemType e){
ElemType * newbase;
if(S.top >= S.size){//若栈顶位标达到所分配容量,则栈满,扩容
newbase = (ElemType * )realloc(S.elem,
(S.size + S.increment) * sizeof(ElemType));
if(NULL == newbase)return OVERFLOW;
S.elem = newbase;
S.size += S.increment;
}
S.elem[S.top++] = e;
return OK;
}
- 栈顶元素出栈
Status Pop_Sq(SqStack &S, ElemType &e)
{
if(NULL == S){
printf("此栈不存在!\n");
exit(-1);
};
if (pS->top <= 0)
{
printf("栈为空!\n");
exit(-1);
}
else
{
e = S.elem[S.top];
S.top--;
return e;
}
}
- 取栈顶元素
Status GetTop_Sq(SqStack &S, ElemType &e)
{
if(NULL == S){
printf("此栈不存在!\n");
exit(-1);
};
if (pS->top <= 0)
{
printf("栈为空!\n");
exit(-1);
}
else
{
e = S.elem[S.top];
return e;
}
}
循环队列
采用顺序结构存储的队列,需要按队列可能的最大长度分配存储空间。队列经常在对头何队尾分别进行出队和入队的操作,需要设置两个位标分别指示对头元素和队尾元素的下一位置,分别叫做对头位标和队尾位标。
循环队列的定义
typedef struct{
ElemType * elem; //存储空间的基址
int front; //对头位标
int rear; //队尾位标,指示队尾元素的下一位置
int maxSize; //存储容量
}
- 初始化操作
//构造一个空队列,最大队列长度为size
Status InitQueue_Sq(SqQueue &Q, int size){
//分配存储空间
Q->elem = (ElemType * )malloc(size * sizeof(ElemType));
if(Q->elem == NULL)return OVERFLOW;
Q.maxSize = size;
Q.front = Q.rear = 0; //置空
return OK;
}
- 销毁队列
- 置为空队列
- 判断是否为空
- 队列长度
- 获取队头元素
- 队尾插入元素(入队)
Status EnQueue_Sq(SqQueue &Q, ElemType &e){
//若队列未满,则插入元素为新队列的队尾元素
if((Q.rear + 1) % maxSize == Q.front) return ERROR;//判断是否为空队列
Q->elem[rear] = e;
Q.rear = (Q.rear + 1) % Q.maxSize;
return OK;
}
- 出队
Status DeQueue_Sq(SqQueue &Q, ElemType &e){
if(Q.front == Q.rear) return ERROR; //对列为空
e = Q.elem[Q.front];
Q.front = (Q.front + 1) % Q.maxSize;//更新队头,队列循环
return OK;
}
顺序表
采用顺序结构表示的线性表称为顺序表。用一组地址连续的存储单元依次存放线性表的数据元素,即以存储位置相邻表示位序相继的两个元素之间的前驱和后继关系。
顺序表的定义
typedef struct{
ElemType * elem; //存储空间的基址
int length; //当前长度
int size; //存储容量
int increment; //顺序表
}SqList; //顺序表