嵌入式团队 栈与队列培训

线性表

线性表的定义

线性表(List):零个或多个相同类型的数据元素的有限序列

顺序线性表结构

在这里插入图片描述线性表的抽象数据类型:

#include <stdio.h>

#define MaxSize 100  //线性表存储空间大小
#define ERROR 0
#define TRUE 1
typedef int ElemType;
typedef int Status;

// 线性表的声明
typedef struct list {
    ElemType data[MaxSize];  //数据元素
    int length;              //线性表的长度
}List;

//线性表的相关操作
void InitList(List* L);        //初始化一个空的线性表L
Status IsEmpty(List L);        //判断线性表是否为空,空返回true
void ClearList(List* L);       //清空线性表
int ListLength(List L);        //返回线性表L的长度即元素个数
void GetElem(List L,int i,ElemType* e); //将线性表L中第i个位置元素值返回给e
int LocateElem(List L,ElemType* e);     //将线性表L中元素值为e的,查找成功返回第i,否则返回error
Status ListInsert(List* L,int i,ElemType e);  //在线性表L中第i个位置插入元素e,成功返回true
Status ListDelete(List* L,int i,ElemType* e); //在线性表L删除第i个位置的元素,并将其值返回给e,成功返回true

*内存地址的计算公式:
LOC(ai) = LOC(a1) + (i-1)c ; c单个元素在内存中所占空间

注意:虽然线性表是由数组实现的,但是“数组的长度”表示该数组存储空间可储存元素的个数,一般是固定值;而“线性表的长度”表示的是目前该线性表中储存的元素个数

线性表的插入和删除

//线性表的插入
Status ListInsert(List *L, int i, ElemType e){
	int k;
	//代码的健壮性
	if(L->length == MaxSize){   //线性表已满
		return ERROR;
	}
	if(i < 1 || i > L->length+1){  //查询的位置不在线性表内
		return ERROR;
	}
	if(i <= L->length){        
		for(k = L->length-1; k >= i-1; k--){   //插入的位置不在表为,插入位置后的每个元素均要往后移一位
			L->data[k+1] = L->data[k];
		}
	}
	L->data[i-1] = e;
	L->length++;
	return TRUE;
}

顺序存储结构和点链表结构的优缺点对比
在这里插入图片描述

栈的定义

栈(stack):是限定仅在表尾进行插入删除操作的线性表
特性:栈尾先进后出
应用
1.网页的返回键
2.递归函数
在这里插入图片描述3.后缀表达式转换
在这里插入图片描述
4.数制转换(作业中布置)


栈的顺序存储结构

#include <stdio.h>

#define MaxSize 100
#define ERROR 0
#define TRUE 1
typedef int ElemType; //视情况而定数据元素类型
typedef int Status;

//栈的定义
typedef struck stack{
	ElemType data[MaxSize];   //储存数据元素
	int top;                  //栈顶指针
}Stack;

注意:top的初始值为-1时表示为空栈,为0时表示栈内有一个元素,为MaxSize-1时栈满,此情况和数组下标对应。


栈的抽象数据类型:
在这里插入图片描述

//进栈操作Push
Status Push(Stack *s, ElemType e){
	//代码的健壮性
	if(s->top == MaxSize-1){  //检测栈满,防止溢出
		return ERROR;
	}
	s->data[++s->top] = e;  //指针+1在栈顶插入目标元素
	return TRUE;
}

//出栈操作Pop
Status Pop(Stack *s, ElemType *e){
	if(s->top == -1){  //检测栈是否为空
		return ERROR;
	}
	*e = s->data[s->top];  //将删除的值保存在e中,并返回其值
	s->top--;              //栈顶指针-1
	return TRUE;
}

两栈共享空间

因为栈的线性存储事先必须规定数组的储存空间大小,会存在一个栈空间不够用的情况,而此时可能又有一个栈储存空间剩余很多造成内存空间浪费,所以提出共享栈的概念:用一个数组来存储两个栈。

思路:top1、top2分别是栈1和栈2的栈顶指针,从数组两端向中间靠拢;
栈空:top1 = -1, top2 = MaxSize
栈满:即top1和top2相遇,top1 + 1 = top2
在这里插入图片描述
具体的代码见书上P95-96

栈的链式存储结构

链栈的结构如下:

typedef struct stackNode{
	ElemType data;
	struct stackNode *next;
}StackNode, *LinkStackPtr;

typedef struct linkStack{
	LinkStackPtr top;  //栈顶指针
	int count;         //元素个数
}LinkSatck;

在这里插入图片描述
在这里插入图片描述栈顶指针相当于单链表的头指针,栈顶元素相当于单链表的首节点,所以链栈中不需要头节点,采用头插法插入元素;

队列

队列(queue):是只允许在一端进行插入操作,在另一端进行删除操作的线性表;
特性:先进先出
在这里插入图片描述

队列的线性结构

typedef struct queue {
    //数据元素
    ElemType data[MaxSize];
    int front;  //头指针
    int rear;   //尾指针
}Queue;

具体的操作和栈差不多就不过多讲解了。

循环队列

一个普通队列可以想到,首部元素不断出队front一直后移,尾部一直插入元素rear一直后移最后会变成假溢出现象,如下图:
在这里插入图片描述
为了解决这个问题提出了循环队列:头尾相接的顺序存储结构

//循环队列结构和上述非循环队列一样
 注意:
 队空:rear == front
 队满:(rear+1) % MaxSize == front  //空出一个元素内存不用
 队列长度公式:(rear-front+MaxSize) % MaxSixe
//初始化一个空队列
Status InitQueue(Queue *Q){
	Q->front = 0;
	Q->rear = 0;    //初始化均为0
	return TRUE;
}
//出队列操作
//1.判断队列是否已空
//2.front后移以为
Status deQueue(SqQueue* Q, QElemType* e) {
    if (Q->front == Q->rear) {    //如果队列空了
        return ERROR;
    }
    
    *e = Q->data[Q->front];
    Q->front = (Q->front + 1) % MAXSIZE; //如果假溢出,就循环到数组前面去
    return OK;
}

队列的链式存储结构

typedef struct QNode {  //队列中的单个数据结点
    ElemType data;
    struct QNode* next;
}QNode,*QueuePtr;

typedef struct queuePtr {  //队列的链表结构
    QueuePtr front, rear;  //对头、队尾指针
}LinkQueue;

在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值