一、栈
1、顺序栈
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h> //开辟空间
#define MAXSIZE 50
//顺序栈的基本算法
typedef struct {
int stack[MAXSIZE];
int top;
}SqStack;
//初始化
void InitStack(SqStack* S) {
S->top = -1;
}
//判断栈是否为空
int StackEmpty(SqStack S) {
if (S.top == -1) {
return 1;
}
return 0;
}
//进栈
void StackPush(SqStack* S,int x) {
if (S->top == MAXSIZE - 1) {
printf("此时栈满");
}
else {
if (S->top == -1) {
S->top += 1;
S->stack[S->top] = x;
}
else {
S->stack[++S->top] = x;
}
//printf("入栈成功");
}
}
//出栈
int StackPop(SqStack* S) {
if (S->top == -1) {
printf("此时为空栈,无法继续出栈");
return - 1;
}
else {
int x = S->stack[S->top];
S->top--;
return x;
}
}
//取栈顶元素
int GetStackTop(SqStack* S) {
if (S->top == -1) {
return -1;
}
int x = S->stack[S->top];
return x;
}
void StackPrint(SqStack* S) {
int num = S->top;
while (num != -1) {
printf("%d ", S->stack[num]);
num--;
}
}
int main() {
SqStack* S = (SqStack*)malloc(sizeof(SqStack));
InitStack(S);
int a;
scanf("%d", &a);
while (a != 0) {
StackPush(S, a);
scanf("%d", &a);
}
StackPrint(S);
a = StackPop(S);
printf("%d",a);
StackPrint(S);
return 0;
}
2、链栈
通过单链表实现
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h> //开辟空间
#define MAXSIZE 50
//链栈
typedef struct StackNode {
int data;
struct StackNode* next;
}StackNode,*LinkStack;
//初始化
void InitStack(LinkStack S) {
S->next = NULL;
S->data = 0;
}
//判断链栈是否为空
int EmptyStack(LinkStack S) {
if (S->data == 0)
return 1;
return 0;
}
//进栈
void StackPush(LinkStack S, int x) {
LinkStack p = (LinkStack)malloc(sizeof(StackNode));
p->data = x;
p->next = S->next;
S->next = p;
S->data++;
}
//出栈
int StackPop(LinkStack S) {
LinkStack p = S->next;
if (p == NULL)
return -1;
S->next = p->next;
int a = p->data;
free(p);
S->data--;
return a;
}
//打印
void StackPrint(LinkStack S) {
LinkStack p = S->next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
}
int main() {
LinkStack S = (LinkStack)malloc(sizeof(StackNode));
InitStack(S);
StackPush(S, 1);
StackPush(S, 2);
StackPush(S, 3);
StackPrint(S);
int x = StackPop(S);
printf("%d", x);
StackPrint(S);
return 0;
}
3.卡特兰数
1. 出栈次序
一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?
下面这个2n是什么意思?
假如有4个数。那每个数有两个情况一个进栈和出栈两种状态。那就一共有8种状态
如果有n个数就有2n种状态。
上面那个n是什么意思?
栈进栈再出栈。假如将进栈标记为1。将出栈标记为-1。出栈和进栈是要平衡的和要为0所以代表n个数里面有几种进栈的状态4个数的话就会有4种进栈的状态。
这里我们记:进栈--- +1 出栈--- -1
有以下结论:
- 合法序列必定总和为0,即num(-1)=num(+1)
- 总和为0的序列不一定合法
有 合法 = - 非法
3.“前缀”:包含首个元素往后数
4.合法序列的特点:对于所有前缀,每一个前缀的和都>=0,且num(-1)=num(+1)
比如: n=3
不合法的:+1,-1,-1,+1,-1,+1
合法的: +1,-1,+1,+1,+1,-1,-1
对于第一个:将第一个“和小于0”的前缀取反,得到一个新序列
-1,+1,+1,+1,-1,+1此时就有4个+1,2个-1
对应n个的话就是将第一个“和小于零”的前缀取反,就得到新序列,且有n+1个+1,n-1个-1
所以A和B是一一对应的
4、表达式求值
【问题描述】栈的应用,给定一个以“#”作为结束符的算式,求出算式的结果
【输入形式】以“#”结尾的表达式,运算数为正整数。每个表达式占一行。
【输出形式】输出表达式运算的结果。
【样例输入1】4+2.53*3-10/5#
【样例输出1】9.59
【样例输入2】3*(7.91-2)#
【样例输出2】17.73
【样例输入3】2.4*3.6/2#
【样例输出3】4.32
【注意】要处理表达式中带小数的数据,不能仅采用getchar去接收数据,请注意查阅资料,看看如何处理。
另外,输出数据请保留2位小数。
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define Size 50
typedef struct {
float elem[Size];
int top;
}SeqStack;
void Init(SeqStack* S) {
S->top = -1;
}
int Empty(SeqStack* S) {
return(S->top == -1 ? TRUE : FALSE);
}
int Full(SeqStack* S) {
return(S->top == Size - 1 ? TRUE : FALSE);
}
int Push(SeqStack* S, float x) {
if (S->top == Size - 1) {
return FALSE;
}
S->top++;
S->elem[S->top] = x;
return TRUE;
}
int Pop(SeqStack* S, float* x) {
if (S->top == -1) {
return FALSE;
}
else {
*x = S->elem[S->top];
S->top--;
return TRUE;
}
}
int Get(SeqStack* S, float* x) {
if (S->top == -1) {
return FALSE;
}
else {
*x = S->elem[S->top];
return TRUE;
}
}
typedef struct {
char elem[Size];
int top;
}StrStack;
void StrInit(StrStack* s) {
s->top = -1;
}
int StrEmpty(StrStack* s) {
return(s->top == -1 ? TRUE : FALSE);
}
int StrFull(SeqStack* s) {
return(s->top == Size - 1 ? TRUE : FALSE);
}
int StrPush(StrStack* s, char x) {
if (s->top == Size - 1) {
return FALSE;
}
s->top++;
s->elem[s->top] = x;
return TRUE;
}
int StrPop(StrStack* s, char* x) {
if (s->top == -1) {
return FALSE;
}
else {
*x = s->elem[s->top];
s->top--;
return TRUE;
}
}
int StrGet(StrStack* s, char* x) {
if (s->top == -1) {
return FALSE;
}
else {
*x = s->elem[s->top];
return TRUE;
}
}
int match(char ch, char str) {
if (ch == '(' && str == ')') {
return TRUE;
}
else if (ch == '[' && str == ']') {
return TRUE;
}
else if (ch == '{' && str == '}') {
return TRUE;
}
else return FALSE;
}
int In(char ch) {
if (ch == '+') {
return TRUE;
}
else if (ch == '-') {
return TRUE;
}
else if (ch == '*') {
return TRUE;
}
else if (ch == '/') {
return TRUE;
}
else if (ch == '(') {
return TRUE;
}
else if (ch == ')') {
return TRUE;
}
else if (ch == '#') {
return TRUE;
}
else return FALSE;
}
char Comper(char x, char ch) {
switch (x)
{
case'+':
if (ch == '+' || ch == '-' || ch == ')' || ch == '#')
return '>';
else if (ch == '*' || ch == '/' || ch == '(')
return '<';
break;
case'-':
if (ch == '+' || ch == '-' || ch == ')' || ch == '#')
return '>';
else if (ch == '*' || ch == '/' || ch == '(')
return '<';
break;
case'*':
if (ch == '(') {
return '<';
}
else {
return '>';
}
break;
case'/':
if (ch == '(') {
return '<';
}
else {
return '>';
}
break;
case'(':
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(')
return '<';
else if (ch == ')')
return '=';
else if (ch == '#')
return '0';
break;
case')':
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == ')' || ch == '#')
return '>';
else if (ch == '(')
return '0';
break;
case'#':
if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(')
return '<';
else if (ch == '#')
return '=';
else if (ch == ')')
return '0';
break;
default:
return '0';
break;
}
}
/*
char Operator(char a, char b) {
int i = 0, j = 0;
char pre[7][7] = {
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='},
};
switch (a) {
case'+':i = 0; break;
case'-':i = 1; break;
case'*':i = 2; break;
case'/':i = 3; break;
case'(':i = 4; break;
case')':i = 5; break;
case'#':i = 6; break;
}
switch (b) {
case'+':j = 0; break;
case'-':j = 1; break;
case'*':j = 2; break;
case'/':j = 3; break;
case'(':j = 4; break;
case')':j = 5; break;
case'#':j = 6; break;
}
return pre[i][j];
}
*/
float Execute(float a, char op, float b) {
switch (op) {
case'+':
return (a + b);
break;
case'-':
return (a - b);
break;
case'*':
return (a * b);
break;
case'/':
if (b != 0)
return (a / b);
else
return 0;
break;
}
}
char ch;
float Evaluation() {
char x, y;
char op;
float a, b, v;
SeqStack data;
StrStack sign;
Init(&data);
StrInit(&sign);
StrPush(&sign, '#'); //提前压一个符号进栈
//printf("biaodashi:\n");
ch = getchar();
StrGet(&sign, &y);
while (ch != '#' || y != '#') {
if (!In(ch)) {
int temp;
int i = 1;
float temp2, a[10] = { 0,0.1,0.01,0.001,0.0001,0.00001 };
temp = ch - '0'; //转换为数字
ch = getchar();
while (!In(ch) && ch != '.') {
temp = temp * 10 + ch - '0';
ch = getchar();
}
temp2 = temp;
if (ch == '.') {
ch = getchar();
for (i = 1; !In(ch); i++) {
temp2 += (ch - '0') * a[i];
ch = getchar();
}
}
Push(&data, temp2);
}
else {
switch (Comper(y, ch)) {
case'<':
StrPush(&sign, ch);
ch = getchar();
break;
case'=':
StrPop(&sign, &x);
ch = getchar();
break;
case'>':
StrPop(&sign, &op);
Pop(&data, &b);
Pop(&data, &a);
v = Execute(a, op, b);
Push(&data, v);
break;
}
}
StrGet(&sign, &y);
}
Get(&data, &v);
return(v);
}
int main() {
float result;
result = Evaluation();
printf("\n%.2f", result);
return 0;
}
二、队列
1、链队列
先进先出
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
}Node;
Node* initQueue() {
Node* Q = (Node*)malloc(sizeof(Node));
Q->data = 0;
Q->next = NULL;
return Q;
}
void inQueue(Node* Q, int data) {
Node* node = (Node*)malloc(sizeof(Node));
Node* q = Q;
node->data = data;
for (int i = 0; i < Q->data; i++) {
q = q->next;
}
node->next = q->next;
q->next = node;
Q->data++;
}
int isEmpty(Node* Q) {
if (Q->data == 0 || Q->next == NULL)
return 1;
return 0;
}
int delQueue(Node* Q) {
if (isEmpty(Q))
return -1;
Node* node = Q->next;
int data = node->data;
Q->next = node->next;
free(node);
Q->data--;
return data;
}
void printQueue(Node* Q) {
Node* node = Q->next;
while(node) {
printf("%d ", node->data);
node = node->next;
}
printf("NULL\n");
}
int main() {
Node* Q = initQueue();
inQueue(Q,1);
inQueue(Q, 2);
inQueue(Q, 3);
inQueue(Q, 4);
printQueue(Q);
int x = delQueue(Q);
printQueue(Q);
printf("%d", x);
return 0;
}
2、循环队列
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 5
//只能放4个数据,牺牲了一个空间去更好判断是否满队
typedef struct Queue {
int front;
int rear;
int data[MAXSIZE];
}Queue;
Queue* initQueue() {
Queue* Q = (Queue*)malloc(sizeof(Queue));
Q->front = Q->rear = 0;
return Q;
}
int isFull(Queue* Q) {
if ((Q->rear + 1) % MAXSIZE == Q->front) {
return 1;
}
return 0;
}
int isEmpty(Queue* Q) {
if (Q->front == Q->rear)
return 1;
return 0;
}
int inQueue(Queue* Q,int data) {
if (isFull(Q)) {
return 0;
}
else {
Q->data[Q->rear] = data;
Q->rear = (Q->rear + 1) % MAXSIZE;
return 1;
}
}
int delQueue(Queue* Q) {
if (isEmpty(Q))
return -1;
int data = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;
return data;
}
void printQueue(Queue* Q) {
int length = (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
int index = Q->front;
for (int i = 0; i < length; i++) {
printf("%d->", Q->data[index]);
index = (index + 1) % MAXSIZE;
}
printf("NULL\n");
}
void main() {
Queue* Q = initQueue();
inQueue(Q, 1);
inQueue(Q, 2);
inQueue(Q, 3);
inQueue(Q, 4);
printQueue(Q);
delQueue(Q);
printQueue(Q);
return 0;
}
3、杨辉三角
#include <stdio.h>
#define MAX 100
#define FALSE 0
#define TRUE 1
//循环队列
typedef struct {
int element[MAX];
int front; //头指针
int rear; //尾指针
} SeqQueue;
//初始化循环队列
void InitQueue(SeqQueue* q) { q->front = q->rear = 0; }
//入队
int EnterQueue(SeqQueue* q, int x) {
if ((q->rear + 1) % MAX == q->front) {
printf("---队列已满---");
return FALSE;
}
q->element[q->rear] = x;
q->rear = (q->rear + 1) % MAX;
return TRUE;
}
//出队
int DeleteQueue(SeqQueue* q, int* x) {
if (q->front == q->rear) {
printf("---队列为空---");
return FALSE;
}
*x = q->element[q->front];
q->front = (q->front + 1) % MAX;
return TRUE;
}
//取对头元素
int GetHead(SeqQueue* q, int* x) {
if (q->front == q->rear)
return FALSE;
*x = q->element[q->front];
return TRUE;
}
//判断队列是否为空
int IsEmpty(SeqQueue* q) {
if (q->front == q->rear)
return TRUE;
else
return FALSE;
}
//打印杨辉三角
void YangHuiTriangle(int N) {
SeqQueue q;
InitQueue(&q);
int n, i, x, temp;
EnterQueue(&q, 1); //第一行元素入队
for (n = 2; n <= N; n++) {
EnterQueue(&q, 1); //第n行第一个元素入队
// N为打印的行数,n为每行的元素个数
for (i = 1; i <= n - 2; i++) { //利用队中第n-1行元素产生第n行的中间n-2个元素并入队
DeleteQueue(&q, &temp); //出队元素赋给temp
printf("%d ", temp); //打印第n-1行的元素
GetHead(&q, &x);
temp = temp + x; //利用第n-1行元素产生第n行元素
EnterQueue(&q, temp); //可以利用画图理解
}
DeleteQueue(&q, &x);
printf("%d ", x); //打印n-1行最后一个元素
EnterQueue(&q, 1);
printf("\n");
}
while (!IsEmpty(&q)) { //打印最后一行
DeleteQueue(&q, &x);
printf("%d ", x);
}
}
//主函数:
int main() {
int N;
scanf("%d", &N);
YangHuiTriangle(N);
printf("\n");
return 0;
}