桌上有一叠牌,从第一张牌(即位于顶面的牌)开始从上往下依次编号为1~n;当至少还剩两张牌时进行以下操作:把第一张牌扔掉,然后把新的第一张放到整叠牌的最后。输入n,输出每次扔掉的牌。
样例输入:
7
样例输出:
1 3 5 7 4 2 6

 1 #include <stdio.h>
 2 int queue[500];
 3 int main()
 4 {
 5     int i, n, front, rear;    //n<=strlen(queue)/2
 6     scanf("%d", &n);
 7     for(i = 0; i < n; i++)
 8         queue[i] = i+1;        //初始化队列
 9     front = 0;                //队首元素的位置
10     rear  = n;                //队尾元素的后一个位置
11     while(front < rear)        //当队列非空
12     {
13         printf("%d ", queue[front++]);    //输出并抛弃队首元素
14         queue[rear++] = queue[front++];    //队首元素转移到队尾
15     }
16     return 0;
17 }
View Code

分析:
  1.队列:每次从排头拿到两个,其中第二个再排到尾部;这种数据结构称为队列(queue),或FIFO表。其中FIFO表示先进先出(First In,First Out),符合日常生活中的排队。
  2.用一个数组queue来实现这个队列,再设两个指针front和rear。尽管运行结果没错,但如果在最后把rear的值打印出来,rear会比n大(恰好是2n)。换言之,在程序运行的后期,queue[rear++]=queue[front++]读写了非法内存(读写非法内存不一定导致程序崩溃)!因此要么把数组空间开大些;要么采用一种称为循环队列的技术,重用已出队元素占用的空间。

C++提供了一种更加简单的处理方式—STL队列:

 1 #include <cstdio>
 2 #include <queue>
 3 using namespace std;
 4 queue<int> q;
 5 int main()
 6 {
 7     int i, n;
 8     scanf("%d", &n);
 9     for(i = 0; i < n; i++)
10         q.push(i+1);    //初始化队列
11     while(!q.empty())    //当队列非空
12     {
13         printf("%d ", q.front());    //打印队首元素
14         q.pop();                    //抛弃队首元素
15         q.push(q.front());            //把新的队首元素加入队列
16         q.pop();                    //抛弃队首元素
17     }
18     return 0;
19 }
View Code

分析:
  1.该程序代码并没有简洁很多,但可读性大大增强:一方面体现在“queue”、“rear”这些望文知义的命名,另一方面体现在STL库的标准性(它是C++不可分割的组成部分)。
  2.减少魔术数(majic number),即不需要事先知道n的大小;减少变量个数(少用了两个变量front和rear)都是提高代码可读性,减少错误可能性的重要手段。

 posted on 2016-04-03 21:48  tostring_char  阅读(276)  评论(0编辑  收藏  举报