【数据结构(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;
}
发布了11 篇原创文章 · 获赞 8 · 访问量 4766

猜你喜欢

转载自blog.csdn.net/u011367208/article/details/83003128
今日推荐