数据结构_杨辉三角(队列实现c语言实现)

杨辉三角除第一行为两个1以外,从第二行开始,每一行的首尾都为1,中间位置的数为上一行其左右两侧数之和,形状如下:
1 1
1 2 1
1 3 3 1
1 4 6 4 1
试编写函数,利用循环队列实现任意行杨辉三角的输出。

如果要求计算并输出杨辉三角前 n 行的值,则队列的最大空间应为 n + 2。(进进出出的)

假设队列中已存有第 k 行的计算结果,并为了计算方便,在两行之间添加一个“0”作为行界值,
则在计算第 k + 1 行之前,头指针正指向第 k 行的“0”,而尾元素为第 k + 1 行的“0”。

由此从左到右依次输出第 k 行的值,并将计算所得的第 k + 1 行的值插入队列

#define  MAXLEN 100 
#define EMPTY_QUEUE_ERROR -9999999
typedef int ElemType;
typedef struct {
	int elem[MAXLEN];    // 用来存队列数据元素的数组
	int front;              // 指示队首在数组中位置的标识量
	int rear;               // 指示队尾在数组中位置的标识量adj.后面的,背面的,后方的
}intQueue;
/*初始化(调整两个位置标识量)*/
void InitQueue(intQueue* pQueue) // 指针类型作为形参,某个队列实例的地址
{
	/**********************************************************
	将该队列实例的队首和队尾标识量置零
	*********************************************************/
	pQueue->front = 0;
	pQueue->rear = 0;
}
/*利用循环队列实现任意行杨辉三角的输出?*/
void  YangHuiTiangle(int n)
{
	int s, e; // s保存 上一行 左侧数据,e保存右侧数据
	intQueue q; // 定义一个队列实例变量q

	InitQueue(&q); // 使用之前需要初始化该队列q

	{ // 预先放入第一行的两个1
		EnQueue(&q,1);
		EnQueue(&q, 1);
	}
	/*后续的行*/
	// 循环: 逐行处理,
	/*将第i行 出队 并输出,
	 生成第i+1行  入队;
	 在出队输出第i行前要先把下一行(即第i+1行)算好并插入队列后才输出,否则下一行的计算就没有输入了)	(注意是从从头(q->front)出队(保存到e),先进先出);*/
	for (int i = 1; i <= n; i++)//i是要输出的行,i+1是要填充的行 
	{
		/*生成第i+1行*/
		EnQueue(&q, 0);// 两行之间增加一个0作为标记
				// 处理第i行的(要生成的)i+2个数据(第i行有i+1个数,额外有一个0作为分隔行的标记数.
		s = 0;/*计算第i行开始前,将保存上一行左边的值的变量初始化为0*/

		for (int j = 1; j <= i + 2; j++)
		{
			// 读取上一行的第一个数据1,存到e中//q.elem[q.front]
			e = DeQueue(&q);//出队一个

			// 计算i行的第j个数据,并入队
			EnQueue(&q, s + e);//入队一个(第i行的第j个数据)

			s = e;  // 这是为何?(在计算同一行的下一个元素时,当前的元素使用的e就是下一个元素的s;

			// 如果j非第i+2个数据,输出s
			/*(e和s是独立于队列之外的两个变量)
			如果j是的i+2个元素,那么刚好是该行的结束标志数0,(与此同时,可以将生成边缘的"1" 也用e+s计算统一起来(边缘值:0+1 = 1或者1+0 = 1 )
			第一行的元素在队列中不是0,但可以在队列之外单独将s初始化为0*/
			{
				/*输出第i行,第i行有i+1个需要输出的元素,(不包括0)*/
				//your multiple lines code
				if (j < i + 2)
				{
					printf("%d ", s);
				}
			}
		}//for(j)
		printf("\n");  // 结束i行,输出换行符
	}//for(i)   
}

//测试, 使用实际例子测试上述函数是否正常工作
/*入队列
将某数据元素x入队列,成功返回1,失败返回0。*/
int  EnQueue(intQueue* pQueue, ElemType x)
{
	// 1、若该队列已满,则入队列失败
	if (IsFull(pQueue))  return 0;

	// 2、若该队列没满,将x写入队尾,然后队尾位置后移
	else
	{
		pQueue->elem[pQueue->rear] = x;// x入队列
		pQueue->rear = (pQueue->rear + 1) % MAXLEN;// 队尾后移
	}


	return 1;
}
/*对头元素出队列*/
int  DeQueue(intQueue* pQueue)
{
	if (!IsEmpty(pQueue))
	{
		/*移动对头元素前保存该值*/
		ElemType temp = pQueue->elem[pQueue->front];

		/*向前移动front有讲究:
		如果是:pQueue->front++,那么front可能会溢出数组,
		所以必须利用循环队列的周期性质(除以周期取余数),保证不溢出*/
		pQueue->front = (pQueue->front + 1) % MAXLEN;
		return temp;/*删除成功的出口*/
	}
	return EMPTY_QUEUE_ERROR;
}

void main()
{
	int n;
	printf("\n\n\t\tYangHui Triangle:\n\nplease input the lines you want!(1~98, 0 to quit)");
	scanf("%d", &n);
	while (n)
	{
		system("cls");/*cls是清屏的,但是它清除的是上一个回车的内容*/
		printf("测试杨辉三角YangHui():\n");
		if (n > 0 && n < 99)
			YangHuiTiangle(n);
		/*准备接收下一个请求:*/
		printf("\n\n\t\tYangHui Triangle:\n\nplease input the lines you want!(1~98, 0 to quit)");
		scanf("%d", &n);
	}
}
posted @ 2024-09-12 15:26  xuchaoxin1375  阅读(165)  评论(0)    收藏  举报  来源