1. 程式人生 > >鏈式表示的佇列——鏈式佇列2——楊輝三角問題

鏈式表示的佇列——鏈式佇列2——楊輝三角問題

列印楊輝三角。楊輝三角是一個由數字排列成的三角形數表,一個8階的楊輝三角如下所示。

                                1
                             1     1
                          1     2     1
                       1     3     3     1
                    1     4     6     4     1
                 1     5    10    10     5     1
              1     6    15    20    15     6     1
           1     7    21    35    35    21     7     1

【分析】

楊輝三角,是二項式係數在三角形中的一種幾何排列,在中國南宋數學家楊輝1261年所著的《詳解九章演算法》一書中出現。在歐洲,帕斯卡(1623----1662)在1654年發現這一規律,所以這個表又叫做帕斯卡三角形。帕斯卡的發現比楊輝要遲393年,比賈憲遲600年。

1.楊輝三角的性質
(1)第一行只有一個數;
(2)第i行有i個數;
(3)第i行最左端和最右端的數均為1;
(4)每個數等於上一行的左右兩個數相加,即第n行的第i個元素等於第n-1行的第i-1和元素和第i個元素之和。
2.構造佇列楊輝三角的第i行元素是根據第i-1元素得到的,因此可以用佇列先儲存上一層元素,然後將佇列依次出隊得到下一層的元素。構造楊輝三角分為2個部分;兩端元素值為1的部分是已知的,剩下的元素是需要構造的部分。

以第8行元素為例,利用佇列來構造楊輝三角(假設Q是順序迴圈佇列)。

(1)在第8行,第一個元素入隊,EnQueue(&Q,1).
(2)第8行中的中間6個元素可以通過已經入隊的第7行元素得到。首先取出隊頭元素並將其出隊Dequeue(&Q,&t);再次將該元素存入臨時陣列中(用於列印輸出),temp[k++]=t; t就是上一行的左邊那一個元素;然後取出右邊那一個元素GetHead(Q,&e), e為隊頭元素,但並不是將其出隊,因為下一次操作還要用到它;然後將左邊的元素和右邊的元素相加t=t+e; 得到本層元素;最後將元素t入隊,EnQueue(&Q,t); 
(3)第7行最後一個元素出隊,DeQueue(&Q,&t), 就是將上一行的最後一個1出隊。
(4)第8行最後一個元素入隊,EnQueue(&Q,1),就是將本行最後一個1入隊。

至此,第8行的所有元素都已經入隊。其它行的入隊操作類似。

注意在迴圈結束後,還有最後一行在佇列裡。在最後一行元素入隊之後。要將其輸出。為了輸出楊輝三角的每一行,需要設定一個臨時陣列temp[MaxSize]用來儲存每一行的元素,然後在結束時輸出該行元素。
LinkQueue.h

#pragma once
#include <iostream>
using namespace std;
#include <malloc.h>
typedef int DataType;
typedef struct QNode
{
	DataType data;
	struct QNode* next;

}LQNode,*QueuePtr;
typedef struct 
{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;
//初始化鏈式佇列
void InitQueue(LinkQueue *LQ)
{
	LQ->front = LQ->rear = (LQNode*)malloc(sizeof(LQNode));
	if (LQ->front==NULL)
	{
		exit(-1);
	}
	LQ->front->next = NULL;

}
//判斷鏈式佇列是否為空
int QueueEmpty(LinkQueue LQ)
{
	if (LQ.rear->next==NULL)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
//將元素e入隊
int EnQueue(LinkQueue *LQ, DataType e)
{
	LQNode *s;
	s = (LQNode*)malloc(sizeof(LQNode));
	if (!s)
	{
		exit(-1);
	}
	s->data = e;
	s->next = NULL;
	LQ->rear->next = s;
	LQ->rear = s;
	return 1;
}

int DeQueue(LinkQueue *LQ, DataType *e)
{
	LQNode *s;
	if (LQ->front==LQ->rear)
	{
		return 0;
	}
	else
	{
		s = LQ->front->next;
		*e = s->data;
		LQ->front->next = s->next;
		if (LQ->rear==s)
		{
			LQ->rear = LQ->front;
		}
		free(s);
		return 1;
	}
}

int GetHead(LinkQueue LQ, DataType *e)
{
	LQNode *s;
	if (LQ.front==LQ.rear)
	{
		return 0;
	}
	else
	{
		s = LQ.front->next;
		*e = s->data;
		return 1;
	}
}

void ClearQueue(LinkQueue *LQ)
{
	while (LQ->front!=NULL)
	{
		LQ->rear = LQ->front->next;
		free(LQ->front);
		LQ->front = LQ->rear;
	}
}

main.cpp

#define MAXSIZE 100
#include "LinkQueue.h"
#include <iomanip>
void PrintArray(int a[],int n,int N);
void YangHuiTriangle(int N);

void main()
{
	int n;
	cout << "請輸入要列印的行數:n=: ";
	scanf("%d", &n);
	YangHuiTriangle(n);


	system("pause");

}

void YangHuiTriangle(int N)
{
	int i, k, n;
	DataType e, t;
	int temp[MAXSIZE];
	LinkQueue Q;
	k = 0;
	InitQueue(&Q);
	EnQueue(&Q, 1);
	for (n = 2; n <= N;n++)
	{
		k = 0;
		EnQueue(&Q, 1);
		for (i = 1; i <= n - 2;i++)
		{
			DeQueue(&Q, &t);
			temp[k++] = t;
			GetHead(Q, &e);
			t = t + e;
			EnQueue(&Q, t);
		}
		DeQueue(&Q, &t);
		temp[k++] = t;
		PrintArray(temp, k, N);
		EnQueue(&Q, 1);
	}

	k = 0;
	while (!QueueEmpty(Q))
	{
		DeQueue(&Q, &t);
		temp[k++] = t;
		if (QueueEmpty(Q))
		{
			PrintArray(temp, k, N);
		}
	}
}

void PrintArray(int a[], int n, int N)
{
	int i; 
	static int count = 0;
	for (i = 0; i < N - count;i++)
	{
		cout << "   ";//三個空格
	}
	count++;
	for (i = 0; i < n;i++)
	{
		cout << setw(6)<< a[i];
	}
	cout << endl;
}

結果: