杨辉三角的打印---------数据结构典型例题

杨辉三角的打印---------数据结构典型例题

现在,给定一个数字N,需要打印N行的杨辉三角

注意:

杨辉三角实际上是
C n m 这 个 问 题 的 解 决 方 法 C^m_n \\ 这个问题的解决方法 Cnm
我认为:如果单独给出一个 C n m C^m_n Cnm的话,应该利用阶乘来进行实现,但是在这里,它要求打印杨辉三角,使用这种“笨”方法显然是行不通。

重点是要利用已经计算的结果。

杨辉三角给出了答案:

下面的一个等于上面两个的和,所以我们可以利用上一步的结果来加快这一次的运算。

杨辉三角的推倒:

C n m = C n − 1 m − 1 + C n − 1 m C^m_n = C_{n-1}^{m-1} + C_{n-1}^{m} Cnm=Cn1m1+Cn1m

可以利用组合数的公式证明:

从M中选出N个(假设有一个元素X)

  1. 选到 X 的情况: C n − 1 m − 1 C_{n-1}^{m-1} Cn1m1
  2. 没有选到 X 的情况: C n − 1 m C_{n-1}^{m} Cn1m

得到证明。

代码实现(queue)

我发现了一个特征:

栈是要一直记录之前的东西,然而目前仅仅专注现在的栈顶。

但是队列是随着过程的进行,前面的会被后面的所替代!!

最后面的一个 1 我自己给补上。

队列的实现请参照我之前写的博文数据结构实现——循环队列

//注意:杨辉三角有一点离谱,所以奉劝各位见好就收,打印20行以内。
#include <stdio.h>
#include <stdlib.h>
typedef int Elem;
typedef struct Queue
{
    Elem *data;
    int head;
    int tail;
    int size;//仅仅是一个功能,程序的判空,判断满并不依赖。
    int MAX_SIZE;//是真正申请的最大值,实际存放MAX_SIZE-1个。
}Queue;
//函数原形声明
Queue *Creat(int max);
int Size(Queue* Q);
Elem GetTail(Queue *Q);
Elem GetHead(Queue *Q);
int Pop(Queue *Q);
int Push(Queue *Q, Elem e);
int Full(Queue* Q);
int Empty(Queue *Q);
int Destroy(Queue* Q);



Queue *Creat(int max)
{
    if(max <= 0)
        return NULL;
    Elem *D = (Elem*)calloc(max + 1, sizeof(Elem));
    if(!D)
        return NULL;
    Queue *Q = (Queue*)malloc(sizeof(Queue));
    if(!Q)
    {
        free(D);
        return NULL;
    }
    Q->MAX_SIZE = max + 1;
    Q->data = D;
    Q->head = 0;
    Q->tail = 0;
    Q->size = 0;
    return Q;
}

int Destroy(Queue* Q)
{
    if(!Q)
        return 0;
    free(Q->data);
    free(Q);
    return 1;
}
int Empty(Queue *Q)
{
    if(Q->head == Q->tail)
        return 1;
    else
        return 0;
}
int Full(Queue* Q)
{
    if((Q->tail+1)%Q->MAX_SIZE == Q->head)
        return 1;
    else
        return 0;
}

int Push(Queue *Q, Elem e)
{
    if(Full(Q))
       return 0;
    Q->data[Q->tail] = e;
    Q->tail = (Q->tail + 1)%Q->MAX_SIZE;
    Q->size += 1;
    return 1;
}

int Pop(Queue *Q)
{
    if(Empty(Q))
        return 0;
    Q->head = (Q->head + 1) % Q->MAX_SIZE;
    Q->size -= 1;
    return 1;
}

Elem GetHead(Queue *Q)
{
    if(Empty(Q))
    {
        *(int *)NULL;//专门让程序crash
    }
    return Q->data[Q->head];
}
Elem GetTail(Queue *Q)
{
    if(Empty(Q))
    {
        *(int *)NULL;//专门让程序crash
    }
    int t;
    t = Q->tail;
    t -= 1;
    if(t >= 0)
        return Q->data[t];
    else
    {
        return Q->data[Q->MAX_SIZE-1];
    }
}
int Size(Queue* Q)
{
    return Q->size;
}

int main()
{
    int N;
    scanf("%d",&N);
    Queue *Q = Creat(N);
    Push(Q,1);
    printf("%6d",1);
    putchar('\n');
    for(int i = 2; i <= N; i++)
    {
        int last = 0;
        for(int j = 1; j <= i - 1; j++)
        {
            int t = 0;
            t = GetHead(Q);
            Pop(Q);

            Push(Q,t+last);
            printf("%6d",t+last);
            last = t;
        }
        Push(Q,1);
        printf("%6d",1);
        putchar('\n');
    }
    Destroy(Q);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值