打印杨辉三角还在用for循环?

本篇采用C语言进行编码示例

最常用方法:

提起打印杨辉三角,我们最容易想到的方法就是建立二维数组,通过for循环来打印,如下:

#include <stdio.h>
int main() {
    int rows;
    printf("请输入需要打印的行数: ");
    scanf("%d", &rows);
    // 创建一个足够大的二维数组存储杨辉三角的值
    int triangle[rows][rows] = {0};
    // 计算杨辉三角的每一行
    for (int i = 0; i < rows; i++) {
        // 每一行的第一个和最后一个数字都是1
        triangle[i][0] = 1;
        triangle[i][i] = 1;

        // 计算该行中间的数值
        for (int j = 1; j < i; j++) {
            triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j];
        }
    }

    // 打印杨辉三角
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j <= i; j++) {
            if (triangle[i][j] != 0) {
                printf("%d ", triangle[i][j]);
            }
        }
        printf("\n");
    }

    return 0;
}

但是,这想起来容易,可时间复杂度是O(n²)的,其随着行数增加,所需的时间将按平方级增长。

那想想有什么更好的方法呢?这就需要数据结构中队列这一结构来优化,接下来将作以介绍:

优化:利用队列进行打印:

如下图,观察即可发现,每个数等于它正上方那一行左边的那个数加上正上方那一行右边的那个数。例如,在杨辉三角中,第3行的中间数字2是由第2行的两个1相加得到的;按这规律来看,那第二行是怎么来的?也没法用第一行加来啊。

这时,我们为了让第二行也能够满足这规律,我们可以在第一行“1”的前面和后面各补上一个“0”,现在,想想,是不是也符合这规律了呢。那么每一行的数值可设为如下图所示那样。

 将各行规律统一后,接下来就对数据进行处理,首先创建一个队列用于存储即将打印的数据,将队列初始化为0,1,0;接下来即可逐个进行扫描,求和(作为下一行的数据),将得到的和放入数据队列中;当当前行(设行号为X)结束后(0为每一行起始的第一个元素,遇到‘0’即标志着进入到了下一行(X+1),同时也标志着当前行(X)结束),同时也意味着下一行(X+1)的数据将生成完成,这时向数据队列中加入一个0作为该行(X+1)数据结束标志,同时也是下一行(X+2)起始的标志。图示如下:

代码实现 :

#include<stdio.h>
#include<stdlib.h>
typedef int ElementType;
typedef struct node{                           //定义结点结构体类型
    ElementType val;
    struct node *next;
}Node;
typedef struct Queue{                           //定义队列结构体类型
   Node *front;
   Node *rear;
//    int flag;

}Queue;
Queue *initQueue(){                               //初始化队列
    // Node *tmp=(Node*)malloc(sizeof(Node));
    // tmp->next=NULL;
    Queue* list=(Queue *)malloc(sizeof(Queue));  
    list->rear=list->front=NULL;
    // list->flag=0;
     return list;
}

int EnQueue(Queue* p,ElementType val){           //入队
   if(!p) return 0;
   Node *tmp=(Node*)malloc(sizeof(Node));
   if(tmp){
    tmp->val=val;
    tmp->next=NULL;
    if(!p->front){
        p->front=p->rear=tmp;

    }
    else{
    p->rear->next=tmp;
    p->rear=tmp;
    }
    
    // if(!p->flag) {
    //     p->front=tmp;
    //     p->flag=1;
    // }
    return 1;
   }
   return 0;
}
int deQueue(Queue*p){                          //出队
    if(!p||!p->front) return 0;
     Node *tmp=p->front;
     p->front=tmp->next;
     ElementType val=tmp->val;
     if(p->front==NULL){
        p->rear=NULL;
     }
       free(tmp);
     return val;
}
int GetFirst(Queue*p){                         //获取第一个元素
     if(!p||p->front==p->rear) return 0;
     ElementType val=p->front->val;
     return val;
}
int isEmpty(Queue *p){                         //判空
    if(!p||p->front==p->rear) return 1;
    return 0;
}
void YanghuiTriangle(int n){                     //打印杨辉三角
    Queue* list1=initQueue();
   EnQueue(list1,0);
    EnQueue(list1,1);
    EnQueue(list1,0);
    int x=0,fir=0;                              //当前出队的元素x,以及出队后队列中第一个元素fir;
     for(int i=0;i<n;i++){                     //控制行数
        do{
        x=deQueue(list1);
        if(x!=0) printf("%d ",x);   
        else  printf("\n");
        fir=GetFirst(list1);                 
        EnQueue(list1,fir+x);                 //fir+x,即为下一行相应的元素,将和存入打印队列,
        }while(fir!=0);                      //当前队列第一个元素为0,则该行打印完毕;
        EnQueue(list1,0);
        
     }

}
//主函数
int main(){
   int n;
   scanf("%d",&n);                            //输入要打印的行数n
   YanghuiTriangle(n);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值