3.1 顺序栈
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#define StackSize 100 //栈元素最多100
typedef int DataType;
//顺序栈的存储结构
typedef struct {
DataType data[StackSize];//存放栈元素的数组
int top;//栈顶位置,即栈顶元素在数组中的下标
}SeqStack;
//1.顺序栈的初始化(初始化一个空的顺序栈)
void InitStack(SeqStack* S) {
S->top = -1;
}
//2.入栈操作
int Push(SeqStack* S, DataType x) { //把x加入到数组中
if (S->top == StackSize - 1) { //栈正好已经满了
printf("栈发生上溢,入栈失败\n");
return 0;
}
//否则,入栈
S->top++;//先将top+1
S->data[S->top] = x;//然后在top的位置填入x
return 1;
}
//3.出栈操作
int Pop(SeqStack* S, DataType* data) { //*data表示要出栈的元素
if (S->top == -1) { //栈中没有元素
printf("栈发生下溢,出栈失败\n");
return 0;
}
//否则,出栈
*data = S->data[S->top];//用*data存储栈顶元素(要删除的元素)
S->top--;//top下移
return 1;
}
//4.取出栈顶元素
int GetTop(SeqStack* S, DataType* data) { //用*data存储栈顶元素
if (S->top == -1) { //栈中没有元素
printf("栈发生下溢,取栈顶元素失败\n");
return 0;
}
//否则
*data = S->data[S->top];
return 1;
}
//5.判空操作
int Empty(SeqStack* S) {
if (S->top == -1) {
return 1;//栈空返回1
}
//否则
return 0;
}
int main() {
DataType x;
SeqStack S;//定义结构体变量S为顺序栈类型
InitStack(&S);//初始化顺序栈
printf("15入栈\n");
Push(&S, 15);
printf("20入栈\n");
Push(&S, 20);
if (GetTop(&S, &x) == 1) {
printf("当前栈顶元素是:%d\n", x);
}
if (Pop(&S, &x) == 1) {
printf("执行一次出栈操作,出栈的是:%d\n", x);
}
if (GetTop(&S, &x) == 1) {
printf("当前栈顶元素是:%d\n", x);
}
printf("请输入待入栈元素:");
scanf("%d", &x);
Push(&S, x);
if (Empty(&S) == 1) {
printf("栈为空\n");
}
else {
printf("栈非空\n");
}
system("pause");
return 0;
}
3.2 链栈
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
//带头结点的链栈
typedef int elemType;
//链栈的结点定义
typedef struct LinkedStackNode {
elemType data;
struct LinkedStackNode* next;
}LStackNode, * LStack;
//初始化链栈
LStack Init_LStack() { //返回空栈(只有一个头结点)
LStack top = (LStack)malloc(sizeof(LStackNode));//生成头结点,top为头指针,指向头结点
if (top != NULL) { //申请成功
top->next = NULL;//头结点的next域置为空
}
return top;//头指针代表整个栈
}
//判空操作
int Empty_LStack(LStack top) {
if (top->next == NULL) {
return 1;//栈为空,返回1
}
else {
return 0;
}
}
//入栈操作(插入新的数据在栈顶)
int Push_LStack(LStack top,elemType x) {
LStack newNode = (LStack)malloc(sizeof(LStackNode));//生成新结点
if (newNode == NULL) {
return 0;//申请结点空间失败
}
//否则
newNode->data = x;
newNode->next = top->next;//新结点的next域指向原来的首元结点
top->next = newNode;//新结点变为首元结点
return 1;
}
//出栈操作(出栈的元素为栈顶元素,即删除首元结点)
int Pop_LStack(LStack top,elemType* x) {
if (top->next == NULL) {
return 0;//空栈
}
//否则
LStack tempNode = (LStack)malloc(sizeof(LStackNode));//生成临时结点(用于存储栈顶元素)
tempNode = top->next;//将首元结点赋给临时结点
*x = tempNode->data;//*x 存储栈顶元素
top->next = tempNode->next;//删除首元结点
free(tempNode);//释放临时结点
return 1;
}
//获取栈的长度(从首元结点开始)
int Length_LStack(LStack top)
{
int count = 0;
while (top->next != NULL)
{
++count;
top = top->next;
}
return count;
}
//取栈顶元素
int GetTop_LStack(LStack top,elemType* x)
{
if (top->next!=NULL)
{
*x = top->next->data;
return 1;
}
//否则
return -1;
}
int main() {
int i, t, x, a[20];
LStack top = Init_LStack();//初始化栈
printf("请依次输入5个数,开始入栈:");
for (i = 0; i < 5; i++)
{
scanf("%d", &a[i]);
Push_LStack(top, a[i]);
}
printf("入栈结束\n");
printf("当前栈长为%d\n", Length_LStack(top));
if (GetTop_LStack(top,&x) == 1) {
printf("当前栈顶元素为:%d\n", x);
}
if (Pop_LStack(top, &x) == 1) {
printf("执行一次出栈操作,出栈的是:%d\n", x);
}
printf("当前栈长为%d\n", Length_LStack(top));
system("pause");
return 0;
}
3.3 循环顺序队列
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#define QueueSize 100 //最大长度
typedef int DataType;
//循环队列的存储结构定义
typedef struct {
DataType data[QueueSize];//存放循环队列元素的数组
int front;//队头元素在数组中的下标
int rear;//队尾元素在数组中的下标
}CirQueue;
//1.循环队列的初始化(将front和rear指向数组中下标为0的位置)
void InitQueue(CirQueue* Q) {
Q->front = Q->rear = QueueSize - 1;
}
//2.求队列的长度
int Length(CirQueue* Q) {
return (Q->rear - Q->front + QueueSize) % QueueSize;
}
//3.入队操作(要入队的元素存放在数组的下标为rear)
int EnQueue(CirQueue* Q, DataType x) {
if ((Q->rear + 1) % QueueSize == Q->front) { //队列已满(上溢)
printf("队列已满,入队失败\n");
return 0;
}
//否则,入队
Q->data[Q->rear] = x;//新元素插入队尾
Q->rear = (Q->rear + 1) % QueueSize;//队尾在循环意义上+1(rear上移一位)
return 1;
}
//4.出队操作(要出队的元素存放在数组的下标为front)
int DeQueue(CirQueue* Q, DataType* data) { //*data为要出队的元素
if (Q->rear == Q->front) { //队列为空(下溢)
printf("队列已空,出队失败");
return 0;
}
//否则,出队
*data = Q->data[Q->front];//保存队头元素
Q->front = (Q->front + 1) % QueueSize;//队头位置在循环意义上+1(front上移一位)
return 1;
}
//5.取队头元素(在数组中下标为front)
int GetHead(CirQueue* Q, DataType* data) { //*data为队头元素
if (Q->front == Q->rear) {
printf("队列为空,取队头元素失败\n");
return 0;
}
//否则
*data = Q->data[Q->front];
return 1;
}
//6.判空操作
int Empty(CirQueue* Q) {
if (Q->rear == Q->front) {
return 1;//队列为空返回1
}
else {
return 0;
}
}
int main() {
DataType x;
CirQueue Q; //定义结构体变量Q为循环队列类型
InitQueue(&Q);//初始化循环队列
printf("10入队,");
EnQueue(&Q, 10);
printf("20入队\n");
EnQueue(&Q, 20);
if (GetHead(&Q, &x) == 1) {
printf("当前队头元素是:%d\n", x);
}
if (DeQueue(&Q, &x) == 1) {
printf("执行一次出队操作,出队元素是:%d\n", x);
}
if (GetHead(&Q, &x) == 1) {
printf("当前队头元素是:%d\n", x);
}
printf("请输入入队元素:");
scanf("%d", &x);
EnQueue(&Q, x);
int length = Length(&Q);
printf("当前队列的元素个数是:%d\n",length );
if (Empty(&Q) == 1) {
printf("队列为空\n");
}
else {
printf("队列非空\n");
}
system("pause");
return 0;
}
3.4 链式队列
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
typedef int DataType;
//链队列的结点结构定义
typedef struct Node {
DataType data;
struct Node* next;
}Node;
//定义链队列
typedef struct {
Node* front;//队头指针,始终指向头结点
Node* rear;//队尾指针,始终指向尾结点
}LinkQueue;
//1.链队列的初始化(生成一个空链队列)
void InitQueue(LinkQueue* Q) {
Node* s = (Node*)malloc(sizeof(Node));//生成头结点
s->next = NULL;//头结点的next域为空
Q->front = Q->rear = s;//头指针和尾指针均指向头结点
}
//2.入队操作(入队尾)
void EnQueue(LinkQueue* Q, DataType x) {
Node* s = (Node*)malloc(sizeof(Node));//生成新结点,s指向它
s->data = x;
s->next = NULL;//s作为尾结点
Q->rear->next = s;//头结点的next域指向s结点
Q->rear = s;//尾指针变为指向s
}
//3.出队操作(首元结点所对应的元素出队)(要判断此时队列中是否只剩头结点和首元结点)
int DeQueue(LinkQueue* Q, DataType* data) { //*data即为出队元素
if (Q->front == Q->rear) { //队空(下溢)
printf("队列为空,出队失败\n");
return 0;
}
//否则,出队
Node* p = Q->front->next;//p指向首元结点(队头元素所在结点)
*data = p->data;//存储队头元素
Q->front->next = p->next;//头结点的next域指向首元结点的下一个结点
if (p->next == NULL) { //首元结点为最后一个结点
Q->rear = Q->front;//尾指针指向头结点
}
free(p);//释放原来的首元结点
return 1;
}
//4.取队头元素
int GetHead(LinkQueue* Q, DataType* data) {
if (Q->front == Q->rear) {
printf("队列为空,取队头元素失败");
return 0;
}
//否则
Node* p = Q->front->next;//p指向首元结点
*data = p->data;
return 1;
}
//5.判空操作
int Empty(LinkQueue* Q) {
if (Q->rear == Q->front) {
return 1;//队列为空返回1
}
else {
return 0;
}
}
//6.链队列的销毁
void Destroy(LinkQueue* Q) {
Node* p = Q->front;//p指向头结点
while (p != NULL) { //依次释放链队列的结点(包括头结点)
Node* temp = p->next;
free(p);
p = temp;
}
}
int main() {
DataType x;
LinkQueue Q;//定义结构体变量Q为链队列类型
InitQueue(&Q);//初始化链队列
printf("10入队列,");
EnQueue(&Q, 10);
printf("20入队列\n");
EnQueue(&Q, 20);
if (GetHead(&Q, &x) == 1) {
printf("当前队头元素是:%d\n", x);
}
if (DeQueue(&Q, &x) == 1) {
printf("执行一次出队操作,出队元素是:%d\n", x);
}
if (GetHead(&Q, &x) == 1) {
printf("当前队头元素是:%d\n", x);
}
printf("请输入入队元素;");
scanf("%d", &x);
EnQueue(&Q, x);
if (Empty(&Q) == 1) {
printf("队列为空\\n");
}
else {
printf("队列不为空\n");
}
system("pause");
return 0;
}
3.5 栈的应用--括号匹配
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
//用顺序栈解决括号匹配问题,每当读入一个左括号则直接入栈,等待相匹配的同类右括号;
// 每当读入一个右括号,将栈顶的左括号出栈,若与当前栈顶的左括号类型相同,则二者匹配
//直到表达式扫描完毕,若栈为空,则表达式匹配。
#define StackSize 100 //栈元素最多100
typedef char DataType; //左括号和右括号都为char类型
//顺序栈的存储结构
typedef struct {
DataType data[StackSize];//存放栈元素的数组
int top;//栈顶位置,即栈顶元素在数组中的下标
}SeqStack;
//1.顺序栈的初始化(初始化一个空的顺序栈)
void InitStack(SeqStack* S) {
S->top = -1;
}
//2.入栈操作
int Push(SeqStack* S, DataType x) { //把x加入到数组中
if (S->top == StackSize - 1) { //栈正好已经满了
printf("栈发生上溢,入栈失败\n");
return 0;
}
//否则,入栈
S->top++;//先将top+1
S->data[S->top] = x;//然后在top的位置填入x
return 1;
}
//3.出栈操作
int Pop(SeqStack* S, DataType* data) { //*data表示要出栈的元素
if (S->top == -1) { //栈中没有元素
printf("栈发生下溢,出栈失败\n");
return 0;
}
//否则,出栈
*data = S->data[S->top];//用*data存储栈顶元素(要删除的元素)
S->top--;//top下移
return 1;
}
//4.取出栈顶元素
int GetTop(SeqStack* S, DataType* data) { //用*data存储栈顶元素
if (S->top == -1) { //栈中没有元素
printf("栈发生下溢,取栈顶元素失败\n");
return 0;
}
//否则
*data = S->data[S->top];
return 1;
}
//5.判空操作
int Empty(SeqStack* S) {
if (S->top == -1) {
return 1;//栈空返回1
}
//否则
return 0;
}
//6.括号匹配函数
int BracketMatch(SeqStack* S, char* str) { //字符串str存储表达式
InitStack(S);//初始化一个空栈
DataType e;
int i = 0;
while (str[i] != '\0') { //当字符串没扫描结束
switch (str[i]) {
//每当读入一个左括号则直接入栈
case '(':
Push(S, '(');
break;
case '{':
Push(S, '{');
break;
case '[':
Push(S, '[');
break;
//每当读入一个右括号,将栈顶的左括号出栈,若与当前栈顶的左括号类型相同,则二者匹配
case ')':
Pop(S, &e);
if (e != '(') {
return 0;
}
break;
case ']':
Pop(S, &e);
if (e != '[') {
return 0;
}
break;
case '}':
Pop(S, &e);
if (e != '{') {
return 0;
}
break;
default:
break;
}
i++;//依次扫描表达式中每个字符
}
//退出while循环代表表达式扫描完成,如果此时栈为空,说明左右括号数量相等
int y = Empty(S);
if (y == 1) { //栈为空
return 1; //匹配成功
}
else {
return 0;
}
}
int main() {
SeqStack S;//定义结构体变量S为顺序栈类型
char str[StackSize];//字符数组接收键盘输入的表达式
printf("请输入表达式的字符串:");
scanf("%s", str);
int result = BracketMatch(&S, str);//调用括号匹配函数
if (result == 0) {
printf("括号匹配失败\n");
}
else {
printf("括号匹配成功\n");
}
system("pause");
return 0;
}
3.6 栈的应用--进制转换
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#define StackSize 100 //栈元素最多100
typedef int DataType;
//顺序栈的存储结构
typedef struct {
DataType data[StackSize];//存放栈元素的数组
int top;//栈顶位置,即栈顶元素在数组中的下标
}SeqStack;
//1.顺序栈的初始化(初始化一个空的顺序栈)
void InitStack(SeqStack* S) {
S->top = -1;
}
//2.入栈操作
int Push(SeqStack* S, DataType x) { //把x加入到数组中
if (S->top == StackSize - 1) { //栈正好已经满了
printf("栈发生上溢,入栈失败\n");
return 0;
}
//否则,入栈
S->top++;//先将top+1
S->data[S->top] = x;//然后在top的位置填入x
return 1;
}
//3.出栈操作
void Pop(SeqStack* S, DataType* data) { //*data表示要出栈的元素
if (S->top == -1) { //栈中没有元素
printf("栈发生下溢,出栈失败\n");
return;
}
//否则,出栈
*data = S->data[S->top];//用*data存储栈顶元素(要删除的元素)
S->top--;//top下移
}
//4.判空操作
int Empty(SeqStack* S) {
if (S->top == -1) {
return 1;//栈空返回1
}
//否则
return 0;
}
//5.数制转换函数
void conversion(int num,int M) { //将10进制数num转换为M进制
//初始化空栈
SeqStack S;
InitStack(&S);
int x;
while (num != 0) {
Push(&S, num % M); //将num取模后的M进制数入栈
num = num / M;//num更新
}
//取模完成后,依次弹出栈顶元素,得到结果
while (Empty(&S) != 1) { //栈非空
Pop(&S,&x);
printf("%d", x);
}
puts("");
}
int main() {
int num;
int M;
printf("请输入要转换的数:");
scanf("%d", &num);
printf("你要将它转换为几进制:");
scanf("%d", &M);
printf("将%d转换为%d进制后的结果为:",num,M);
conversion(num, M);
system("pause");
return 0;
}