1. 程式人生 > >編寫一個能將給定非負整數列表中的數字排列成最大數字的程式

編寫一個能將給定非負整數列表中的數字排列成最大數字的程式

問題描述:例如,給定[50,2,1,9],最大數字為95021

問題分析:將輸入的數字進行排列組合,使得最終得到的整數是最大的

問題實現需要注意

  • 因為需要提取數列中每個數字的首位,並能夠和本來的數字建立聯絡,所以這裡採用結構體的知識。
  • 有可能存在多個首位數字相同的情況,所以,我們需要對於對這種情況手動編寫函式來甄別大小,同時還要採取以首位數字為依據的分片化操作處理數列。

程式程式碼特點

  • 運用結構體知識實現數字聯絡
  • 判斷數字是否最大的思想
  • 函式之間的呼叫

C語言程式碼

#include<stdio.h>
#include<time.h>
#include<Windows.h>
int num[20], number; struct MyStruct { int x, y; }MyStruct[20], temp_struct;
  • 這裡使用num[20]這個陣列儲存數列,number記錄數字個數
  • MyStruct為結構體名稱,x儲存數字,y儲存首位數字。同時定義了MyStruct[20],這個結構體陣列。temp_struct為結構體陣列排序時用的中間變數。
void Random()
{
    for (int i = 0; i < 15; i++)
    {
        num[i] = rand() % 1000;
        //scanf
("%d", &num[i]); MyStruct[i].x = num[i]; number += 1; } }
  • 這裡為輸入函式。此刻預設生成3位及3位以下的15個隨機數為一個數列。
  • 將預處理的陣列num中的數字儲存到MyStruct[i].x裡面
/*傳入數字x,需要判斷位數y,z==1 得到這個數字的總位數。返回分割後的數字*/
int Divide(int x, int y, int z)
{
    int substitute_x = x, i = 1;
    while (substitute_x>=10)    {substitute_x /= 10
;i += 1;} int wei = i; if (z == 1) return wei; for (int i = 1; i <= wei - y; i++) {x /= 10;} return x; }
  • 這裡為一個數字處理函式。
  • 實現的功能是:傳入數字x,y指需要該函式返回的位數的數字,預設從高位起,倘若z=1,則直接返回該數字總位數。列如:Divide(789,1,0),則返回7。Divide(789,1,1),則返回3。
/*分割槽處理函式,陣列的起始位置x,結束位置y*/
void Piece(int x, int y)
{
    for (int j = x; j < y ; j++)
    {
        for (int i = x; i < x + y - j; i++)
        { 
            if (Divide(MyStruct[i].x, 1, 1) > Divide(MyStruct[i + 1].x, 1, 1))
            {
                if (Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1), 0) < MyStruct[i + 1].x)
                    temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                else if (Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1), 0) == MyStruct[i + 1].x)
                {
                    if (MyStruct[i + 1].x * 10 + Divide(MyStruct[i].x, 1, 0) > Divide(MyStruct[i].x, (Divide(MyStruct[i + 1].x, 1, 1)) + 1, 0))
                        temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                }
            }

            else if (Divide(MyStruct[i].x, 1, 1) < Divide(MyStruct[i + 1].x, 1, 1))
            {
                if (MyStruct[i].x < Divide(MyStruct[i + 1].x, Divide(MyStruct[i].x, 1, 1), 0))
                    temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                else if (MyStruct[i].x == Divide(MyStruct[i + 1].x, Divide(MyStruct[i].x, 1, 1), 0))
                {
                    if (MyStruct[i].x * 10 + Divide(MyStruct[i + 1].x, 1, 0) < Divide(MyStruct[i + 1].x, (Divide(MyStruct[i].x, 1, 1)) + 1, 0))
                        temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                }
            }

            else
            {
                if (MyStruct[i].x<MyStruct[i+1].x)
                    temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
            }
        }
    }
}
  • 這裡僅是針對首位相同的數列進行的排列操作。
  • Piece(int x, int y):這裡的x為陣列的首位下標,y為最後一個數字的下標。
  • 本文將兩個首位相同的數字之間的大小比較做了如下分類:1.前者數字的位數大於後者。2.後者數字的位數大於前者。3.兩個數字位數相同。

以前者位數大於後者位數為例進行分析

if (Divide(MyStruct[i].x, 1, 1) > Divide(MyStruct[i + 1].x, 1, 1))
            {
                if (Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1), 0) < MyStruct[i + 1].x)
                    temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                else if (Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1), 0) == MyStruct[i + 1].x)
                {
                    if (MyStruct[i + 1].x * 10 + Divide(MyStruct[i].x, 1, 0) > Divide(MyStruct[i].x, (Divide(MyStruct[i + 1].x, 1, 1)) + 1, 0))
                        temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                }
            }
  • Divide(MyStruct[i].x, 1, 1) 引用Divide(int x,int y,int z)函式。傳入當前數字MyStruct[i].x,需要判斷位數為1位,z=1。說明需要返回MyStruct[i].x數字的位數。
if (Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1), 0) < MyStruct[i + 1].x)
  • 這裡是將位數較多的那一個數字選取與位數較小的數字的位數與位數較小的數字進行比較。列如:779與78比較。Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1)返回77,MyStruct[i + 1].x為78
temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
  • 這裡是兩個結構體變數的交換
else if (Divide(MyStruct[i].x, Divide(MyStruct[i + 1].x, 1, 1), 0) == MyStruct[i + 1].x)
                {
                    if (MyStruct[i + 1].x * 10 + Divide(MyStruct[i].x, 1, 0) > Divide(MyStruct[i].x, (Divide(MyStruct[i + 1].x, 1, 1)) + 1, 0))
                        temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
                }
  • 當兩個返回值相同時怎麼辦?比如:778和77
if (MyStruct[i + 1].x * 10 + Divide(MyStruct[i].x, 1, 0) > Divide(MyStruct[i].x, (Divide(MyStruct[i + 1].x, 1, 1)) + 1, 0))
  • 這條語句即是精華部分。意思是:將77*10得到770再加上778的首位7,得到777,然後與778比較。
/*處理函式*/
void Operate()
{
    for (int i = 0; i < number; i++)    { MyStruct[i].y = Divide(num[i], 1, 0); }

    for (int j = 0; j < number - 1; j++)
    {
        for (int i = 0; i < number - 1 - j; i++)
        {
            if (MyStruct[i].y < MyStruct[i + 1].y)
                temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
        }
    }
    for (int i = 0; i < number;)
    {
        int get = MyStruct[i].y, xx = i;

        while (MyStruct[i].y == get)    
            i++;

        int yy = i - 1;
        Piece(xx, yy);
    }
}
  • 這個函式的目的是得到不同數字的首位,並從大到小排序,並針對相同首位進行分片,並傳入Piece()
for (int i = 0; i < number; i++)    { MyStruct[i].y = Divide(num[i], 1, 0); }
  • 呼叫Divide函式,將預處理的陣列num中的數字的首位儲存到MyStruct[i].y裡面。
for (int j = 0; j < number - 1; j++)
    {
        for (int i = 0; i < number - 1 - j; i++)
        {
            if (MyStruct[i].y < MyStruct[i + 1].y)
                temp_struct = MyStruct[i], MyStruct[i] = MyStruct[i + 1], MyStruct[i + 1] = temp_struct;
        }
    }
  • 這裡用到了氣泡排序,將首位數字從大到小排序
for (int i = 0; i < number;)
    {
        int get = MyStruct[i].y, xx = i;

        while (MyStruct[i].y == get)    
            i++;

        int yy = i - 1;
        Piece(xx, yy);
    }
  • 將同一片的資料首尾下標傳入Piece中處理。
void Print()
{
    for (int i = 0; i < number; i++)
        printf("%d ", MyStruct[i].x);
    printf("\n---------------------------------------------\n");
}
  • 列印函式
int main()
{
    for (int i = 0; i < 100 ; i++)
    {
        Random();
        Operate();
        Print();
        number = 0;
    }
    return 0;
}
  • 主函式。這裡要注意,如果使用隨機生成方式。number=0語句很重要。