堆栈出栈顺序个数详解——卡兰特数

  参考了多篇博客之后,终于弄懂了,写下了方便以后复习!首先简单介绍一下堆栈的运行方式,先入后出,First In Last Out(FILO),即若我们将1-4顺序放入堆栈中,则出栈顺序为4 3 2 1。了解堆栈的出栈顺序后,接下来介绍一下若将1-n顺序放入堆栈中,可能的出栈情况个数。本文将介绍两种方法,第一种通过01字符串考虑,第二种通过利用组合数学,考虑数字1的出栈所在位置进行分析。

01字符串

考虑以下的情况:
  *
  * *
  * * *
  * * * *
  上述的三角形方针表示只能向下走或向右走,(向下走表示入栈,向右走表示出栈),那上述的三角形方针就表示123可能的出栈顺序。下面的图就表示出栈顺序为231。
在这里插入图片描述
  如果用1表示入栈,0表示出栈,则1-n的入栈与出栈顺序就可由2n个01字符串表示。那所有情况就是C(n,2n),当然里面包含许多不满足堆栈实际情况的出入栈顺序。
  由上述三角形方针可知,如果出栈个数多于入栈个数的话是不可能存在的情况,我们上述举的例子出栈顺序为231的话,整体用01表示为110100(1入栈,2入栈,2出栈,3入栈,3出栈,1出栈),那假设01串为100110的话肯定是不可能的,入栈才1个数,出栈就两个数了,通过这个例子可以明白为何出栈个数多于入栈个数的话是不可能存在的,即0的个数大于1的个数。下面来分析这种不满足情况的有多少种:
  已知整个01数字串中包含n个0,n个1。在第一次出现0的个数比1的个数多时,假设1出现了k次,0出现了k+1次,则之后的01序列中1的个数为n-k,0的个数为n-k-1,若将后半部分的0换成1,1替换成0,则总体的数字串包含1有k+n-k-1=n-1个,同理0的个数有n+1个。那就可以求出来不满足情况的有C(n+1,2n)个。

  因此,若将1-n顺序放入堆栈中,共有情况C(n,2n)-C(n+1,2n)种。

利用组合数学

  假设数字1在出栈顺序中占第k位(从第一位开始),则数字1之前包含k-1个数字,1之后包含n-k个数字,且数字1之前出现的数字一定为2-k,数字1之后出现的数字为k+1到n。如图所示:
在这里插入图片描述
  数字1入栈后,数字2-k以某种顺序入栈并出栈,之后数字1出栈,(满足假设在第k位出栈),之后数字k+1到n以某种顺序入栈并出栈。数字2-k以某种顺序入栈并出栈的情况种数为f(k-1),数字k+1到n以某种顺序入栈并出栈的情况种数为f(n-k),因此由乘法原理可知,数字1在第k位出栈的情况种数为f(k-1)·f(n-k)
  数字1又可能出现在第1位,第2位,第3位,…,第k位,…,第n位。

  • 出现在第1位的情况总数为f(0)·f(n-1)
  • 出现在第2位的情况总数为f(1)·f(n-2)
  • 出现在第3位的情况总数为f(2)·f(n-3)
  • 出现在第k位的情况总数为f(k-1)·f(n-k);
  • 出现在第n位的情况总数为f(n-1)·f(0);

因此总的可能个数为f(0)·f(n-1)+f(1)·f(n-2)+f(2)·f(n-3)+…+f(k-1)·f(n-k)+f(n-1)·f(0)。这个就是卡兰特数了,最后结果f(n) = C(n,2n)-C(n+1,2n)

  • 11
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,以下是一个简单的C语言代码实现堆栈和入的函数。 ``` #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 int stack[MAX_SIZE]; int top = -1; void push(int value) { if (top == MAX_SIZE - 1) { printf("Error: Stack overflow\n"); return; } top++; stack[top] = value; } int pop() { if (top == -1) { printf("Error: Stack underflow\n"); return -1; } int value = stack[top]; top--; return value; } int main() { push(1); push(2); push(3); printf("%d\n", pop()); printf("%d\n", pop()); printf("%d\n", pop()); return 0; } ``` 希望对你有所帮助! ### 回答2: 当然可以帮您用C语言编写一个堆栈的函数。 首先,我们需要定义一个堆栈的结构体,用来存储堆栈的数据和相关信息。结构体中包括堆栈的最大容量、当前容量和一个指向存储数据的数组的指针。例如: ```c #define MAX_SIZE 100 typedef struct { int top; int capacity; int* data; } Stack; ``` 接下来,我们需要初始化堆栈。这个函数将为堆栈分配内存,并将top和capacity的值都设置为0。例如: ```c void initStack(Stack* stack) { stack->top = 0; stack->capacity = MAX_SIZE; stack->data = (int*)malloc(sizeof(int) * MAX_SIZE); } ``` 然后,我们编写一个入函数,用于向堆栈中添加元素。这个函数将检查堆栈是否已满,如果没有满,则将元素添加到堆栈顶部,并将top加1。例如: ```c void push(Stack* stack, int value) { if (stack->top == stack->capacity) { printf("堆栈已满,无法入!\n"); return; } stack->data[stack->top++] = value; printf("元素 %d 入成功!\n", value); } ``` 接着,我们编写一个函数,用于从堆栈中移除元素。这个函数将检查堆栈是否为空,如果不为空,则将顶部元素移除,并将top减1。例如: ```c int pop(Stack* stack) { if (stack->top == 0) { printf("堆栈为空,无法!\n"); return -1; } int value = stack->data[--stack->top]; printf("元素 %d 成功!\n", value); return value; } ``` 最后,记得在程序结束时释放堆栈的内存,以免造成内存泄漏。例如: ```c void destroyStack(Stack* stack) { free(stack->data); } ``` 以上就是用C语言实现堆栈的基本函数。您可以根据需求在这个基础上进一步扩展功能。希望对您有帮助! ### 回答3: 以下是用C语言编写的堆栈和入函数的示例: ```c #include <stdio.h> #define STACK_SIZE 10 int stack[STACK_SIZE]; int top = -1; // 入函数 void push(int data) { if (top < STACK_SIZE - 1) { stack[++top] = data; printf("%d 入成功!\n", data); } else { printf("堆栈已满,无法入!\n"); } } // 函数 int pop() { if (top >= 0) { int data = stack[top--]; printf("%d 成功!\n", data); return data; } else { printf("堆栈为空,无法!\n"); return -1; // 用-1表示堆栈为空 } } int main() { push(10); // 将10入 push(20); // 将20入 push(30); // 将30入 int data = pop(); // 操作 printf("的元素是:%d\n", data); return 0; } ``` 运行这段代码后,将会得到以下输: ``` 10 入成功! 20 入成功! 30 入成功! 30 成功! 的元素是:30 ``` 这个例子实现了一个简单的整数类型堆栈。`push()`函数用于将数据压入堆栈,`pop()`函数用于从堆栈中弹数据。在这个例子中,我们使用了一个数组来模拟堆栈,通过变量`top`来记录堆栈顶部的位置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值