【数据结构(C++)】用链队列计算杨辉三角

目录

第一节  概述

第二节  开源代码


 第一节  概述

杨辉三角是二项式系数在三角形中的一种几何排列,是中国古代数学的杰出研究成果之一。它把二项式系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来,是一种离散型的、数与形的结合。

在实际计算杨辉三角时,最常使用的数学规律是:

  1. 除第1行只有唯一的元素1外,每行的首元素和尾元素都是1;

  2. 从第3行开始,中间的每一个元素是上一行左右2个元素的和。

图1 杨辉三角

 

由于杨辉三角的特殊性,我们采用链式队列结构存储与计算。


第二节  源代码

既然涉及到链式存储结构,首先要定义结点的数据存储格式。

每一个结点包含一个数据域和一个指针域,数据域用于存放队列的真实元素,指针域则指向队列中的下一个结点。

/**
 * 编者注:
 * 由于使用了C++作为编程语言
 * 建议使用*.hpp作为头文件的后缀名
 * *.h是C语言使用的头文件后缀名
 */
#pragma once
template <class DataType>
struct Node
{
    DataType data;
    Node<DataType> *next;
};

队列是一种具有操作限制的表结构:只能在队列开头删除元素(出队)、读取元素(读队头),只能在队列末尾添加元素(入队)。除了这些基本操作,队列还需要判空。

由于是链式存储,必须由我们自己编写构造函数与析构函数,用于开辟和释放队列的结点。

/**
 * 编者注:
 * 下面的类与上面的结构体是配套的
 * 强烈建议放在同一个头文件中
 */
template <class DataType>
class LinkQueue
{
  private:
    Node<DataType> *front, *rear; //队头、队尾指针

  public:
    LinkQueue();               //构造函数,初始化一个空的链队列
    ~LinkQueue();              //析构函数,释放链队列中各结点的存储空间
    void EnQueue(DataType x);  //将元素x入队
    DataType DeQueue();        //将队头元素出队
    DataType GetQueue() const; //取链队列的队头元素
    bool Empty() const;        //判断链队列是否为空
};
#include <iostream>
#include <iomanip> //输出格式设置
/**
 * 记得在此处引入上面的头文件(建议使用*.hpp)
 */
using namespace std;

template <class DataType>
LinkQueue<DataType>::LinkQueue()
{
    Node<DataType> *s = new Node<DataType>;
    s->next = nullptr;
    front = rear = s;
}

template <class DataType>
LinkQueue<DataType>::~LinkQueue()
{
    Node<DataType> *p = nullptr;
    while (front != nullptr)
    {
        p = front->next;
        delete front;
        front = p;
    }
}

template <class DataType>
void LinkQueue<DataType>::EnQueue(DataType x)
{
    Node<DataType> *s = new Node<DataType>; //申请节点s
    s->data = x;                            //将数据存入结点
    s->next = nullptr;                      //封闭队尾
    rear->next = s;                         //将新节点接入原队尾
    rear = s;                               //更新队尾
}

template <class DataType>
DataType LinkQueue<DataType>::DeQueue()
{
    Node<DataType> *p = nullptr;
    DataType x;
    if (rear == front)
        throw "错误:下溢!";
    p = front->next;
    x = p->data;           //暂存队头元素
    front->next = p->next; //摘链
    if (p->next == nullptr)
        rear = front;
    delete p;
    return x;
}

template <class DataType>
DataType LinkQueue<DataType>::GetQueue() const
{
    if (front != rear)
        return (front->next->data);
    else
        throw "错误:空队列!";
}

template <class DataType>
bool LinkQueue<DataType>::Empty() const
{
    return (front == rear);
}

现在,终于到了解释主算法的时候了!每一句的逻辑都注释在代码中:

//杨辉三角,其中n是总行数
void nCr(int n)
{
    LinkQueue<int> queue;         //初始化空队列
    for (auto i = 1; i <= n; i++) //对于每一行
    {
        if (i == 2) //在第2行时
        {
            cout << setw(3) << queue.DeQueue() << endl;
            queue.EnQueue(1); //加上行首的元素1
        }
        else if (i > 2) //第3行及之后
        {
            queue.EnQueue(1);                   //补上行首的元素1
            for (auto j = 1; j <= (i - 2); j++) //每行的求和元素比行序号少2
            {
                auto temp = queue.DeQueue(); //将求和元素的左元素(上一行)出队并另存
                cout << setw(3) << temp << " ";
                queue.EnQueue(temp + queue.GetQueue()); //读取右元素(上一行),将左右元素相加并入队
            }
            cout << setw(3) << queue.DeQueue() << endl; //输出上一行末尾的元素1
        }
        queue.EnQueue(1); //在行尾补元素1
    }
    //若队列非空,输出最后一行的元素
    while (!queue.Empty())
    {
        cout << setw(3) << queue.DeQueue() << " ";
    }
    cout << endl
         << endl;
}

 

当然可以,我帮你查找一下 C 语言链式队列打印杨辉三角的代码: ``` #include <stdio.h> #include <stdlib.h> // 链式队列节点 typedef struct QNode { int data; struct QNode *next; } QNode, *QueuePtr; // 链式队列结构体 typedef struct { QueuePtr front; // 队头指针 QueuePtr rear; // 队尾指针 } LinkQueue; // 初始化队列 void InitQueue(LinkQueue *Q) { Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode)); if (!Q->front) { exit(-1); } Q->front->next = NULL; } // 入队列 void EnQueue(LinkQueue *Q, int e) { QueuePtr p = (QueuePtr)malloc(sizeof(QNode)); if (!p) { exit(-1); } p->data = e; p->next = NULL; Q->rear->next = p; Q->rear = p; } // 出队列 int DeQueue(LinkQueue *Q) { int e; QueuePtr p; if (Q->front == Q->rear) { return -1; } p = Q->front->next; e = p->data; Q->front->next = p->next; if (Q->rear == p) { Q->rear = Q->front; } free(p); return e; } // 返回队列长度 int GetQueueLength(LinkQueue *Q) { int len = 0; QueuePtr p = Q->front->next; while (p) { len++; p = p->next; } return len; } // 打印杨辉三角,num 表示打印多少行 void print_yh_triangle(int num) { int i, j, a[num]; LinkQueue Q; InitQueue(&Q); for (i = 0; i < num; i++) { for (j = 0; j <= i; j++) { if (j == 0 || j == i) { a[j] = 1; } else { a[j] = DeQueue(&Q) + DeQueue(&Q);// 取出队列的前两个元素相加,组成新的元素入队列 } printf("%d ", a[j]); EnQueue(&Q, a[j]);// 新元素入队列 } printf("\n"); } } int main() { print_yh_triangle(5); return 0; } ``` 希望这个代码对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️是纱雾酱哟~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值