前言
本文主要介绍栈、队列和数组。
一、栈
1.栈的基本概念
栈:只容许在一端进行插入或删除的线性表。
栈顶:线性允许进行插入删除的那一端。
栈底:固定的、不允许进行插入与删除的另一端。
2.栈的基本操作
A.常用操作
定义栈、初始化栈、判空栈、入栈、出栈、读栈。
B. 实战代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50
typedef int ElempType;
//0 栈的定义
typedef struct {
ElempType data[50];
int top;
}SqStack;
//1 初始化
void InistStack(SqStack& S)
{
S.top = -1;//代表栈为空
}
//2 栈判空
bool StackEmpty(SqStack S)
{
if (S.top == -1)
return true;
else
return false;
}
//3 入栈
bool Push(SqStack &S, ElempType x)
{
if (S.top == MaxSize - 1)//栈满,报错
return false;
S.data[++S.top] = x;//指针先加1,再入栈
return true;
}
//4 出栈
bool Pop(SqStack &S, ElempType &x)
{
if (S.top == - 1)//栈空,报错
return false;
x=S.data[S.top--];//先出栈,指针再减1
return true;
}
//5 读栈
bool GetTop(SqStack S, ElempType& x)
{
if (S.top == -1)//栈空,报错
return false;
x = S.data[S.top];//x记录栈元素
return true;
}
int main()
{
//0-定义栈
SqStack S;//定义栈,先进后出 FILEO LIFO
//1-初始化
InistStack(S);//初始化
//2-判空栈
bool flag;
flag = StackEmpty;
if (flag)
{
printf("栈是空的\n");
}
//3-入栈
Push(S, 3);//入栈元素3
Push(S, 4);//入栈元素4
Push(S, 5);//入栈元素5
//4-出栈
ElempType m;//用来存放拿出的元素
Pop(S, m);
//5-读栈
GetTop(S, m);//获取栈顶元素
printf("栈顶元素为%d\n", m);
}
3.栈的链式存储
核心代码
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
二、队列
1.队列的基本概念
队列:一种操作受限制的线性表,只允许在表的一端进行插入,而在表的另一端进行删除。
入队(进队):向队列中插入元素。
出队(离队):删除列表中的元素。
队头(Front):允许删除的一端。
队尾(Front):允许插入的一端。
特点:先进先出(First In First Out,FIFO)
2.队列的顺序存储结构
A.队列的顺序存储
定义:
//伪代码,队列的定义
#define MaxSize 50
typedef int ElempType;
typedef struct {
ElempType data[MaxSize];//存放队列元素
int front, rear;//队头指针与队尾指针
} SqQueue;
B.循环队列
含义:将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环。
1
C.循环队列的操作
C.1 初始化
void InitQueue(SqQueue& Q) {
Q.rear = Q.front = 0;
}
C.2 判队空
bool isEmpty(SqQueue Q) {
if (Q.rear == Q.front) return true;//队空条件
else return false;
}
C.3 入队
bool EnQueue(SqQueue& Q, ElempType x) {
if((Q.rear+1)%MaxSize == Q.front) //队满报错
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;//队尾指针加1取模
return true;
}
C.4 出队
bool DeQueue(SqQueue& Q, ElempType x) {
if (Q.rear == Q.front) //队空报错
return false;
x=Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;//队头指针加1取模
return true;
}
D 实战代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50
typedef int ElempType;
//0 定义
typedef struct {
ElempType data[MaxSize];//存放队列元素
int front, rear;//队头指针与队尾指针
} SqQueue;
//1 初始化
void InitQueue(SqQueue& Q) {
Q.rear = Q.front = 0;
}
//2 判断空
bool isEmpty(SqQueue Q) {
if (Q.rear == Q.front) return true;//队空条件
else return false;
}
//3 入队
bool EnQueue(SqQueue& Q, ElempType x) {
if((Q.rear+1)%MaxSize == Q.front) //队满报错
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;//队尾指针加1取模
return true;
}
//4 出队
bool DeQueue(SqQueue& Q, ElempType x) {
if (Q.rear == Q.front) //队空报错
return false;
x=Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;//队头指针加1取模
return true;
}
int main(){
//0-定义
SqQueue Q;
//1-初始化
InitQueue(Q);
//2-判空
bool ret_1 = isEmpty(Q);
if (ret_1)
printf("队列为空\n");
else
printf("队列不为空\n");
//3-入队
EnQueue(Q, 4);
EnQueue(Q, 3);
bool ret_2 = EnQueue(Q, 2);
if (ret_2)
printf("入队成功\n");
else
printf("入队失败\n");
//4-出队
int x=0;
bool ret_3 = DeQueue(Q, x);
if (ret_3)
printf("出队成功\n",);
else
printf("出队失败\n");
}
3.队列的链式存储结构
A. 队列的链式存储
含义:队列的链式表示称为链队列,它是一个同时带有队头指针与队尾指针的单链表。
队列链的描述:
typedef struct { // 链式队列结点
ElempType data;
struct LinkNode* next;
} LinkNode;
typedef struct { //链式队列
ElempType data;
LinkNode* front,*rear; //队列的队头指针与队尾指针
} LinkQueue;
B. 链式队列的基本操作
B.1 初始化
void InitQueue(LinkQueue& Q) {
Q.rear = Q.front = (LinkNode*)malloc(sizeof(LinkNode));//建立头结点
Q.front->next = NULL;//初始为空
}
B.2 判断空
bool IsEmpty(LinkQueue Q) {
if (Q.rear == Q.front) return true;//队空条件
else return false;
}
B.3 入队
void EnQueue(LinkQueue& Q, ElempType x) {
LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x; s->data = NULL;//创建新节点,插入到链尾
Q.rear->next = s;
Q.rear = s;
}
B.4 出队
bool DeQueue(LinkQueue &Q, ElempType x) {
if (Q.rear == Q.front) return false;//队空报错
LinkNode *p = Q.front->next;
x = p->data;
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;//若原队列中只有一个节点,删除后变空
free(p);
return true;
}
C实战代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50
typedef int ElempType;
//0定义
typedef struct { // 链式队列结点
ElempType data;
struct LinkNode *next;
} LinkNode;
typedef struct { //链式队列
ElempType data;
LinkNode* front, * rear; //队列的队头指针与队尾指针
} LinkQueue;
//1 初始化
void InitQueue(LinkQueue & Q) {
Q.rear = Q.front = (LinkNode*)malloc(sizeof(LinkNode));//建立头结点
Q.front->next = NULL;//初始为空
}
//2 判断空
bool IsEmpty(LinkQueue Q) {
if (Q.rear == Q.front) return true;//队空条件
else return false;
}
//3 入队
void EnQueue(LinkQueue &Q, ElempType x) {
LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x; s->data = NULL;//创建新节点,插入到链尾
(Q.rear)->next = s;
Q.rear = s;
}
//4 出队
bool DeQueue(LinkQueue & Q, ElempType x) {
if (Q.rear == Q.front) return false;//队空报错
LinkNode* p = Q.front->next;
x = p->data;
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;//若原队列中只有一个节点,删除后变空
free(p);
return true;
}
int main() {
//0-定义
LinkQueue Q;
//1-初始化
InitQueue(Q);
//2-判空
bool ret_1 = IsEmpty(Q);
if (ret_1)
printf("队列为空\n");
else
printf("队列不为空\n");
//3-入队
EnQueue(Q, 4);
EnQueue(Q, 3);
//4-出队
ElempType x;
bool ret_3 = DeQueue(Q, x);
if (ret_3)
printf("出队成功,出队元素为%d\n",x);
else
printf("出队失败\n");
}
4. 双端队列
A. 含义
允许两端都可以进行入队与出队操作的队列。
B. 输出受限的双端队列
允许在一端进行插入与删除,而在另一端只允许插入的双端队列称为输出受限的双端队列。
C. 输入受限的双端队列
允许在一端进行插入与删除,而在另一端只允许删除的双端队列称为输出受限的双端队列。
三、栈和队列的应用
1. 栈在括号匹配中的应用
先进的左括号等待后进的右括号匹配。
2. 栈在表达式求值中的应用
3. 栈在递归中的应用
//斐波拉契数列
int Fib(int n){
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
printf("一次上1-2台阶,一共有%d种走法\n", Fib(10));
}
4. 栈在层次遍历中的应用
5. 栈在计算机系统中的应用
速度匹配:缓冲器;
资源竞争:分时使用;
四、数组和特殊矩阵
1. 数组的定义
由n(n>=1)个相同类型的数据元素构成的有限序列。
2. 数组的存储结构
3. 矩阵的压缩存储结构
压缩存储:为多个值相同的元素只分配一个存储空间,对零元素不发分配存储空间。
A. 对称矩阵
B. 三角矩阵
C. 三对角矩阵
D. 稀疏矩阵