《算法》第四版2.1.14

这道题的意思是给一摞纸牌,上面标有大小的数字,让你在一定条件限制下完成排序,条件是你只能看到上面两张牌,要么交换两张牌,要么将最上面的牌放到这摞牌的底部。

从这道题的描述可以发现,纸牌的交换类似于冒泡排序。
先复习一下什么是冒泡排序。
冒泡排序通过重复地走访待排序列,发现相邻的两项顺序颠倒,就交换两项,不断循环重复,直到没有元素交换的时候(每次循环都能确定一个元素的固定位置,循环n次就能排序完成),循环终止完成排序。名字由来是因为在排序的过程中,越小的元素会经由交换慢慢地“浮”到顶端。
代码如下:

void bubblesort(int num[])
{
    int n = 5;
    int i = 0;
    int swapped = 1;
    while(swapped == 1){
        swapped = 0;
        for(i = 1; i < n; i++){
            if(num[i - 1] > num[i]){
                int temp = num[i];
                num[i] = num[i - 1];
                num[i - 1] = temp;
                swapped = 1;
            }
        }
    }
}

一般情况下,我们知道一共就循环n次,还可以这样写:

void bubblesort(int num[])
{
   int n = 5;
   int i = 0;
   for(i = 0; i < n; i++){
       for(int j = 0; j < n - i - 1; j++){
           if(num[j] > num[j + 1]){
               int temp = num[j];
               num[j] = num[j + 1];
               num[j + 1] = temp;
           }
       }
   }
}

下面针对限制条件,尝试改变冒泡排序算法来解决这个问题。可以将纸牌抽象成数字,进行排序。
比如:3 1 6 2 4

  1. 比较第一个数和第二个数的大小,将小的数放在第一位。
    3 > 1,交换,变成 1 3 6 2 4
  2. 将第一位进行标志,然后将第一位放在最右边。
    3 6 2 4 *1
  3. 比较第一位和第二位,将小的数放在第一位,然后将第一位放在最右边。
    3 < 6, 不用交换,直接将3放在最右边。6 2 4 *1 3
  4. 重复第3步,直到标志位走到第二位,退出循环。
    6 *1 3 2 4
  5. 直接将6放在最右边,结束第一轮的循环。*1 3 2 4 6
  6. 返回第一步重新循环,直到在该循环中没有交换发生,退出循环,完成排序。

说明:每一个循环产生的结果和使用冒泡排序(无限制情况下)的结果是相同的。
下面是参考代码:

#include <stdio.h>
void bubblesort(int num[]);
void swap(int num[], int i, int j);
void order(int num[]);//将第一位的数字放到最右边

int main()
{
    int num[] = {12,4,7,5,0};
    int i;

    printf("Original:\n");
    for(int i = 0; i < 5; i++){
        printf("%d ",num[i]);
    }
    printf("\n");

    bubblesort(num);

    printf("Result:\n");
    for(int i = 0; i < 5; i++){
        printf("%d ",num[i]);
    }

    return 0;
}

void bubblesort(int num[])
{
    int flag = 0;
    int i;
    int swapped = 1;
    int cnt = 1;
    while(swapped == 1){
        swapped = 0;
        if(num[0] > num[1]){
            swap(num,0,1);
            swapped = 1;
        }
        flag = 4;

        order(num);

        while(flag != 1){
            if(num[0] > num[1]){
                swap(num,0,1);
                swapped = 1;
            }
            order(num);
            flag --;
        }
        order(num);
        printf("Iteration %d:\n",cnt);
        cnt++;
        for(int i = 0; i < 5; i++){
            printf("%d ",num[i]);
        }
        printf("\n\n");
    }
}

void swap(int num[], int i, int j)
{
    int temp = num[i];
    num[i] = num[j];
    num[j] = temp;
}

void order(int num[])
{
    int temp = num[0];
    int i = 0;
    for(i = 0; i < 4; i++){
        num[i] = num[i + 1];
    }
    num[4] = temp;
}

运行效果:

Original:
12 4 7 5 0 
Iteration 1:
4 7 5 0 12 

Iteration 2:
4 5 0 7 12 

Iteration 3:
4 0 5 7 12 

Iteration 4:
0 4 5 7 12 

Iteration 5:
0 4 5 7 12 

Result:
0 4 5 7 12

猜你喜欢

转载自www.cnblogs.com/zhaijiayu/p/11507311.html