栈和队列是特殊的线性表,逻辑结构和一般线性表相同,对元素的操作方式不同
堆栈只能在结构的一端进行插入和删除的操作
队列在一端进行插入,在另一端进行删除
栈是限制在表的一端进行插入和删除的线性表
允许进行插入和删除操作的一端称为栈顶,另一端成为栈底
多个元素依次进栈,后进栈的元素必然先出栈
堆栈又被称为后进先出表(LIFO) last in first out
LIFO:Last in First Out
堆栈设有一个栈顶指针标志栈顶位置
顺序栈利用一组连续的存储单元存放栈中的数据元素,同顺序表
回顾一下顺序表的结构
typedef char DataType;
typedef struct List
{
DataType* list;
int length;
int MaxLength;
}ListType;
顺序栈的结构
typedef char DataType;
typedef struct STACK
{
DataType* stackArray; //存储元素的空间指针
int top; //栈顶指针,存储栈顶元素的下标
int MaxLength; //堆栈最大的可分配空间数量
}Stack;
在这里,DataType是某种数据类型,以上面代码举例就是char类型
存储数据的变量stackArray仅仅是一个指针,使用顺序栈之前要进行数组的初始化,长度为maxLength
将数组的0下标单元作为栈底,将栈顶元素的下标存储在栈顶指针top中,随元素进出栈而变化
top等于-1时表示空栈(top是栈顶指针,存储栈顶元素的下标)
top等于maxLength-1时表示满栈
如果将栈置为空栈,将top设为-1即可
代码详解:
1.创建栈,只需要提供栈的大小,返回栈的指针,创建失败返回NULL
//创建一个新的栈
Stack* CreatStack(int length)
{
Stack* stack = (Stack*)malloc(sizeof(Stack));
if (stack != NULL)
{
stack->stackArray = (DataType*)malloc(sizeof(DataType) * length);
if (stack->stackArray == NULL)
return NULL;
stack->top = -1;
stack->MaxLength = length;
}
return stack;
}
2.清空栈,只需指向栈的指针
使栈为空
//清空栈
void ClearStack(Stack* stack)
{
stack->top = -1;
}
3.销毁栈,只需要提供指向栈的指针
//销毁栈
void DestoryStack(Stack* stack)
{
free(stack->stackArray);
free(stack);
}
4.弹栈(出栈),只需提供指向栈的指针,返回弹出栈顶的元素
Pop在栈顶删除元素,top-1
//弹栈(出栈)
int Pop(Stack* stack, DataType* data)
{
if (stack->top != -1)
{
*data = stack->stackArray[stack->top];
stack->top = stack->top - 1;
return 1;
}
else
{
return 0;
}
}
5.压栈(入栈),只需提供指向栈的指针和要入栈的元素
top+1走到空位置,在栈顶top处插入元素作为新的栈顶
//压栈(入栈)
void Push(Stack* stack, DataType data)
{
if (stack->top < stack->MaxLength - 1)
{
stack->top = stack->top + 1;
stack->stackArray[stack->top] = data;
}
}
6.取得栈的大小
//得到栈的大小
int GerLength(Stack* stack)
{
return stack->top + 1;
}
7.取得栈顶元素但不出栈
//取得栈顶元素,但是不出栈
int GetStackPeek(Stack* stack, DataType* data)
{
if (stack->top >= 0)
{
*data = stack->stackArray[stack->top];
return 1;
}
else
{
return 0;
}
}
拓展:使用scanf_s函数输入
int main()
{
char a = 0;
scanf_s("%c", &a, sizeof(a)); //scanf_s("%c",&a,1)
return 0;
}
scanf_s有三个参数
最后一个是变量a所占据空间的大小(单位为字节)
这里可以写1,也可以写sizeof(a)
如果a为整型的话,第三个参数就为4,或者sizeof(a)
如果输入整型数据,scanf函数的里面的sizeof()是在所有取地址的后面,而输入字符,每个取地址后面需要有一个sizeof()
举例说明
int main()
{
char a = 0, b = 0; //字符型
scanf_s("%c %c", &a, sizeof(a), &b, sizeof(b));
printf("%c %c", a, b);
return 0;
}
int main()
{
int a = 0; //整型
int b = 0;
scanf_s("%d %d", &a, &b, sizeof(a),sizeof(b));
printf("%d %d", a, b);
return 0;
}
重点:输入字符串
int main()
{
char arr[5]={0};
scanf_s("%s",&arr,sizeof(arr));
return 0;
}
输入字符的个数时,一定是比数组的空间个数小的,
比如像上面的代码只能输入1-4个字符,而不是5个,不然会出错。
arr[4]装的是一个'\0',字符串结束标志
以下是总体代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<string.h> //strlen()的头文件
using namespace std;
typedef char DataType;
typedef struct STACK
{
DataType* stackArray;
int top;
int MaxLength;
}Stack;
//创建一个新的栈
Stack* CreatStack(int length)
{
Stack* stack = (Stack*)malloc(sizeof(Stack));
if (stack != NULL)
{
stack->stackArray = (DataType*)malloc(sizeof(DataType) * length);
if (stack->stackArray == NULL)
return NULL;
stack->top = -1;
stack->MaxLength = length;
}
return stack;
}
//清空栈
void ClearStack(Stack* stack)
{
stack->top = -1;
}
//销毁栈
void DestoryStack(Stack* stack)
{
free(stack->stackArray);
free(stack);
}
//弹栈(出栈)
int Pop(Stack* stack, DataType* data)
{
if (stack->top != -1)
{
*data = stack->stackArray[stack->top];
stack->top = stack->top - 1;
return 1;
}
else
{
return 0;
}
}
//压栈(入栈)
void Push(Stack* stack, DataType data)
{
if (stack->top < stack->MaxLength - 1)
{
stack->top = stack->top + 1;
stack->stackArray[stack->top] = data;
}
}
//得到栈的大小
int GerLength(Stack* stack)
{
return stack->top + 1;
}
//取得栈顶元素,但是不出栈
int GetStackPeek(Stack* stack, DataType* data)
{
if (stack->top >= 0)
{
*data = stack->stackArray[stack->top];
return 1;
}
else
{
return 0;
}
}
//测试用主函数
int main()
{
//定义栈的大小
const int MAXLENGTH = 100;
//创建一个栈
Stack* stack = CreatStack(MAXLENGTH);
printf("连续输入不超过10个字符作为入栈字符:\n");
//定义一个字符串
char ch[10];
//将输入的内容保存在字符串中
scanf("%s", &ch, sizeof(ch));
//strlen函数计算字符串的长度,不包括'\0'
for (int i = 0; i < strlen(ch); i++)
{
Push(stack, ch[i]); //入栈
}
printf("字符出栈序列为:\n");
//弹栈并输出直到栈空
while (GerLength(stack)> 0)
{
char out; //定义一个字符
if (Pop(stack, &out))
printf("%c", out); //将出栈的字符保存在out中
}
DestoryStack(stack);
return 0;
}
strlen所作的仅仅是一个计数器的工作
它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描
直到碰到第一个字符串结束符’\0’为止,然后返回计数器值
此处
头文件:string.h(C++ cstring)
格式:strlen (字符数组名)
功能:计算字符串s的长度,不包括’\0’在内
说明:返回s的长度,不包括结束符NULL。