1. 程式人生 > >ACM基礎之排序演算法

ACM基礎之排序演算法

在ACM基礎知識中,排序是一種比較基礎但又比較重要的思想,熟練地掌握排序演算法十分有必要。排序的方法比較多,這裡重要介紹三種排序:選擇排序、插入排序、氣泡排序。
一、選擇排序
1、基本思想:在要排序的一組數中,選出最小的數與第一個數交換,然後再在剩下的數中選出最小的數與第二個數交換….直到第n-1個數與第n個數比較為止;
例:3 1 5 2 4
第一步,選出這五個數中最小的數,即 1;
第二步,將1與此陣列的第一個數3交換,此時陣列為:1 3 5 2 4;
第三步,在後四個數中選出最小的數,即 2;
第四步,將 2 與 3 交換,此時陣列為:1 2 5 3 4;
第五步,以此類推,將3與5交換,此時陣列為:1 2 3 5 4;
第六步,將4與5交換,此時陣列為:1 2 3 4 5,排序完畢。
2、程式碼詳解:

#include<stdio.h>
int main()
{
    int array[10];
    int i,j,k,temp;
    for(int l=0;l<10;l++)
        scanf("%d",&array[l]);
    for(i=0;i<10;i++)
    {
        k = i;                      //用k執行迴圈,用i儲存資料
        for(j=i+1;j<10;j++)             //將第i個元素與後面的元素比較
            if(array[k] > array
[j]) k = j; //交換標號 temp = array[k]; //交換兩個標號下的元素的值 array[k] = array[i]; array[i] = temp; } for(int l=0;l<10;l++) printf("%d ",array[l]); printf("\n"); }

這裡默認了10個數排序,在排序的for迴圈裡(大家應該能看出來哪個是用來排序的for迴圈),外層的for迴圈代表著從第一個數開始比較直到比較到最後一個,然後把 i 賦值給k,也就是說現在array[k]的值和array[i]的值相等,從第 i+1個數的後一個數開始比較,如果發現array[j]比array[k]小,那麼就把 j 賦值給k,然後繼續比較,直到最後一個數為止。也就是說,在執行完11、12、13行的程式碼之後,array[k] 中儲存的應該是剩下的所有數中最小的數了。就算array[i] 就是最小值的話,那麼array[k]中儲存的也應該是array[i] 的值。所以,在14、15、16行中,將array[k]和array[i]交換。
二、插入排序
1、基本思想:將一個元素插入到一個已經排序好的有序表中,從而得到一個新的、記錄數增1的有序表。即:先將序列的第1個記錄看成是一個有序的子序列,然後從第二個記錄逐個進行插入,直到整個序列有序為止;
例:3 1 5 2 4
第一步:先將3預設為一個排序好的序列;
第二步:將1 插入該有序表,將1 插在3的前面,此時該有序表為 1 3;
第三步:將5 插入該有序表,將5插在3的後面,此時該有序表為 1 3 5;
第四步:將2插入該有序表,將2插在1 和 3 中間,此時有序表為 1 2 3 5;
第五步:將4插入該有序表,將4插在3 和 5 中間,此時有序表為 1 2 3 4 5,排序完畢。
2、程式碼詳解:

#include<stdio.h>
int main()
{
    int a[10];
    int i,temp,p;
    for(int j = 0;j<10;j++)
        scanf("%d",&a[j]);              //輸入十個數
    for(i=1;i<10;i++)                   //從第二個數開始
    {
        temp = a[i];
        p = i-1;                        //從後往前開始比較
        while(p>=0 && temp<a[p])        //注意判斷條件:p>=0 && temp<a[i]
        {
            a[p+1] = a[p];              //依次向後移一位
            p--;
        }
        a[p+1] = temp;                  //將該位置的值覆蓋
    }
    for(int j = 0;j<10;j++)             //輸出
        printf("%d ",a[j]);
}

這裡依然默認了十個數的排序,第8行到18行程式碼為排序程式碼。由於對於陣列中的第一個數我們預設它為一個排好序的有序表,所以我們從第二個數開始進行插入操作。對於陣列中的第 i + 1個數,也就是a[i],我們先將a[i] 賦值給temp,然後從第i個數,即a[i-1]開始比較。
注意while迴圈中的條件,p>=0 && temp < a[p]。我們在這裡假設我們要將4 插入 1 2 3 5這個有序表中,及將a[4]插入到這個表中,讓a[4] ,即temp= 4先與 a[3] = 5比較,發現符合條件,執行while迴圈:把a[3]賦值給a[4],即a[4] = 5,也就是把5 向後移一個位置,然後p–也就此時p = 2;然後將temp = 4與a[2] = 3比較,發現不符合條件。則a[p+1] = a[2+1] = a[3] = 4,插入完畢。而對於將1插入到3這個有序表中這個操作,在第一次執行完while迴圈之後,p = -1。然後再執行while迴圈的時候,發現p不大於等於0 ,即不符合條件,所以a[-1+1] = a[0] = 1,插入完畢。
三、氣泡排序
1、基本思想:通過無序區中相鄰記錄關鍵字間的比較和位置的交換,使關鍵字最小的記錄如氣泡一般逐漸網上“漂浮”,直至“水面”;
例:3 1 5 2 4
第一步:從後往前比較,將2 和4 比較發現2 < 4 不需要交換;
第二步:隨後比較5 和 2,發現5 < 2,交換,序列變成3 1 2 5 4;
第三步:比較1 和 2 ,發現 1 < 2,不需要交換;
第四步:比較3 和 1,發現 3 > 1,交換,序列變成1 3 2 5 4,至此第一個大的迴圈結束;
第五步:再從最後開始,比較5 和 4,交換,序列變成 1 3 2 4 5;
第六步:比較2 和 4,不需要交換;
第七步:比較3 和 2,交換,序列變成1 2 3 4 5,排序結束。
2、程式碼詳解:

#include<stdio.h>
int main()
{
    int a[10],temp;
    for(int i=0;i<10;i++)
        scanf("%d",&a[i]);                  //輸入
    for(int i=1;i<=9;i++)                   //大的迴圈
        for(int j=8;j>=0;j--)
        {
            if(a[j]>a[j+1])                 //相鄰的兩個元素比較
            {                       //如果前面的元素比後面的大
                temp = a[j];                    //交換兩個元素
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
    for(int i=0;i<=9;i++)                   //輸出
        printf("%d ",a[i]);
}

思考一下:對於一個有n個元素的序列,最多需要多少個大的迴圈呢?
答案是n-1。這是為什麼呢?設想,一個氣泡排序,最“慘烈”的情況就是:第一次大的迴圈,把最小的數“冒”到最前面,第二次大的迴圈,把第2小的數“冒”到前面….一直到第n-1次迴圈,把n-1“冒”到前面。而當n-1已經在它的位置上的時候,n自然已經在最後的位置了。所以在第7到第17行程式碼中,最外層的迴圈一共要進行9次,即n-1次(在這裡n預設為10),然後j從8開始迴圈,如果前面的數比後面的大,那麼交換兩個元素的位置。
這裡外層迴圈進行了n-1次,這是為了取最大值,其實還有一種寫法,那就是當檢測到一次大的迴圈已經沒有元素髮生互換之後,就可以中止迴圈了。程式碼的實現這裡不再給出。

以上大概就是三種排序的思想及程式碼實現。其實,這三種排序的結果並不重要,但是這種演算法、這種思想大家一定要會,程式碼一定要會寫。其實如果單單就排序的結果而言,C++函式中的sort函式要快捷得多,也方便得多,但是一些題目中,你不會這種排序思想是寫不出來的,所以瞭解這些排序思想,對於我們的ACM之路還是很有必要的

相關推薦

ACM基礎排序演算法

在ACM基礎知識中,排序是一種比較基礎但又比較重要的思想,熟練地掌握排序演算法十分有必要。排序的方法比較多,這裡重要介紹三種排序:選擇排序、插入排序、氣泡排序。 一、選擇排序 1、基本思想:在要排序的一組數中,選出最小的數與第一個數交換,然後再在剩下的數中選

基礎算法系列排序演算法-3. 直接插入排序 並用其解決HDU 1106 排序

      我們之前已經學習了氣泡排序和二分查詢兩種基本演算法,本篇文章我們將一起學習下一個基礎演算法——直接插入排序演算法。  直接插入排序      直接插入排序,從這個名字來看,是不是讓你想到了什麼場景?!對了,就是打撲克牌的場景,我們每摸一張牌,是不是按照一定的次

基礎算法系列排序演算法-5. 快速排序

我們之前學習了氣泡排序演算法,我們知道,在氣泡排序過程中,只對相鄰的兩個元素進行比較,因此每次交換兩個相鄰的元素時只能消除一個逆序。如果能通過兩個(不相鄰)元素的一次交換,消除多個逆序,則會大大加快排序的速度。而這就是本篇文章講述的另一種基本排序演算法——快速排序演算法。

基礎算法系列排序演算法-6.折半插入排序 並用解決hdu 1412問題

       我們之前已經瞭解了5種基礎演算法,是否自己找了一些題練練手呢~話不多說,讓我們進入第6中基礎演算法的學習吧。本篇我們將學習又一種排序演算法——折半插入排序演算法,跟上篇我們所學習的快速排序有點像,都是建立在我們之前學習的演算法的基礎上改進而來的。從這個演算法的名

基礎算法系列排序演算法-7.希爾排序 並解決hdu 1425問題(java實現)

       我們從最初的氣泡排序演算法,到上篇文章的折半插入排序演算法,我們一共學習了5種排序演算法,相信以大家的聰明才智肯定都消化了^_^。在本篇文章中,我們又將學習第6種排序演算法——希爾排序演算法。那就讓我們直奔主題吧。 希爾排序  讓我們回想一下直接插入排序演算

ACM基礎結構體排序

問題 E: 【排序】排名 時間限制: 1 Sec  記憶體限制: 64 MB 題目描述 班上剛測試了幾門課,現在資訊科技課的老師要分析一些功課之間的成績關係,看看每個人的資訊科技課成績排名以及數學課成績排名,並按資訊科技課的成績從高到低排列,如果兩個

C++——演算法基礎排序——氣泡排序(優化)

今天,大白跟大家聊一聊氣泡排序的優化,我們都知道氣泡排序是幾種穩定排序中比較快的一種排序了。 但是,演算法的優化永無止境,革命尚未成功,“同志”仍須努力(嘻嘻)。 今天大白再看了教科書之後,並且融入了一些自己的想法,使得氣泡排序更加優化了。 首先,我們來看一組圖: bu

Go基礎--排序和查找操作

ear () ola 方法 math https swa blog png 排序操作主要都在sort包中,導入就可以使用了import("sort") 常用的操作 sort.Ints:對整數進行排序sort.Strings:對字符串進行排序sort.Float64s:對

資料結構基礎排序

轉自:http://www.cnblogs.com/edisonchou/p/4713551.html   排序 排序(Sorting)是計算機內經常進行的一種操作,其目的是將一組“無序”的記錄序列調整為按關鍵字“有序”的記錄序列。如何進行排序,特別是高效率地進行排序時計算機工

資料結構排序演算法(五)

// 索引堆 function swap(arr, x, y) {             var temp = arr[x];         

《資料結構與演算法排序演算法(插入排序、希爾排序

3、插入排序 插入排序的基本操作就是將一個數據插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料,演算法適用於少量資料的排序,時間複雜度為O(n^2),是穩定的排序方法。插入演算法把要排序的陣列分成兩部分:第一部分包含了這個陣列的所有元素,但將最後一個元素除外(讓陣列多一個空間才

《資料結構與演算法排序演算法(氣泡排序、選擇排序

排序(Sorting) 是計算機程式設計中的一種重要操作,它的功能是將一個數據元素(或記錄)的任意序列,重新排列成一個關鍵字有序的序列。 排序演算法分類: 一、非線性時間比較類排序 1、交換排序(氣泡排序、快速排序) 2、插入排序(簡單插入排序、布林排序) 3、選擇排序(簡單選擇

演算法基礎_排序演算法

一.O(n^2)的排序演算法 O(n^2)的排序演算法 基礎 編碼簡單,易於實現,是一些簡單情景的首選 在一些特殊情況下,簡單的排序演算法更有效 簡單的排序演算法思想衍生出複雜的排序演算法 作為子過程,改進更復雜的排序演算法

STL排序演算法

1.merge() 以下是排序和通用演算法:提供元素排序策略 merge: 合併兩個有序序列,存放到另一個序列。 例如: vecIntA,vecIntB,vecIntC是用vector宣告的容器,vecIntA已包含1,3,5,7,9元素,vecIntB已包含2,4,6,8元素

在Object-C中學習資料結構與演算法排序演算法

筆者在學習資料結構與演算法時,嘗試著將排序演算法以動畫的形式呈現出來更加方便理解記憶,本文配合Demo 在Object-C中學習資料結構與演算法之排序演算法閱讀更佳。 目錄 選擇排序 氣泡排序 插入排序 快速排序 雙路快速排序 三路快速排序 堆排序 總結與收穫

Kata系列排序演算法的選擇排序

Kata系列之排序演算法的選擇排序 /*** 簡單選擇排序* 一個原地(in-place)排序,適用於小檔案。* 由於選擇操作時基於鍵值的且交換操作只在需要時才執行,* 所以選擇排序長使用者數值較大和鍵值較小的檔案。* * 在未排序序列中找到最小元素,存放到排序序列的起始位置

Kata系列排序演算法的氣泡排序

Kata系列之排序演算法的氣泡排序: /*** 靜態變數*/private static int tempNum=0;/*** 氣泡排序* * 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。* 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最* 後一對。在這一點,

資料結構排序演算法

JavaScript實現排序演算法 程式碼實現 const ArrayList = function() { let array = [], length = 0; this.insert = function(item) {

Go基礎--排序和查詢操作

排序操作主要都在sort包中,匯入就可以使用了 import("sort") 常用的操作 sort.Ints:對整數進行排序 sort.Strings:對字串進行排序 sort.Float64s:對浮點數進行排序 使用例子: package main import ( "s

資料結構排序演算法(五)-直接插入排序,希爾排序,直接選擇排序

直接插入排序:時間複雜度:O(n^2) 基本演算法思路是:把後面待排序的記錄按其關鍵字的大小逐個插入到一個已經排好序的有序序列中,直到所有記錄插完為止,得到一個新的有序序列。(無序插入前面有序) 演算