第8章排序 本章中主要介绍下列内 谷: 插入排序 交换排序 选择排序 归并排序 基数排序 西加大学数学与信息学院
ぜ喙【 ᣁᎾ ݙ߫ᴀゴЁЏ㽕ҟ㒡ϟ ᆍ˖ l ᦦܹᥦᑣ l Ѹᤶᥦᑣ l 䗝ᢽᥦᑣ l ᔦᑊᥦᑣ l ᭄ᥦᑣ ߎ䗔
81基本概念 8,2插入排序 8.3交换排序 8.4选择排序 8.5归并排序 8.6基数排序 西加大学数学与信息学院
8.1 ᴀὖᗉ 8.2 ᦦܹᥦᑣ 8.3 Ѹᤶᥦᑣ 8.4 䗝ᢽᥦᑣ 8.5 ᔦᑊᥦᑣ 8.6 ᭄ᥦᑣ
8.1基本概念 关键字是数据元素中的某个数据项。如果某个数 据项可以唯一地确定一个数据元素,就将其称为主关 键字;否则,称为次关键字。 排序是把一组无序地数据元素按照关键字值递增 (或递减)地重新排列。如果排序依据的是主关键 字,排序的结果将是唯一的, 排序算法的稳定性如果在待排序的记录序列中有 多个数据元素的关键字值相同,经过排序后,这些数 据元素的相对次序保持不变,则称这种排序算法是稳 定的,否则称之为不稳定的。 西加大学数学与信息学院
8.1 ᴀὖᗉ ݇䬂ᄫ ᰃ᭄ܗ㋴ЁⱘᶤϾ᭄乍DŽབᵰᶤϾ᭄ 乍ৃҹଃϔഄ⹂ᅮϔϾ᭄ܗ㋴ˈህᇚ݊⿄ЎЏ݇ 䬂ᄫ˗৺߭ˈ⿄Ў݇䬂ᄫDŽ ᥦᑣ ᰃᡞϔ㒘᮴ᑣഄ᭄ܗ㋴ᣝ✻݇䬂ᄫؐ䗦 ˄䗦ޣഄ˅䞡ᮄᥦ߫DŽབᵰᥦᑣձⱘᰃЏ݇䬂 ᄫˈᥦᑣⱘ㒧ᵰᇚᰃଃϔⱘˈ ᥦᑣㅫ⊩ⱘ〇ᅮᗻ བᵰᕙᥦᑣⱘ䆄ᔩᑣ߫Ё᳝ Ͼ᭄ܗ㋴ⱘ݇䬂ᄫؐⳌৠˈ㒣䖛ᥦᑣৢˈ䖭ѯ᭄ ܗ㋴ⱘⳌᇍᑣֱᣕϡবˈ߭⿄䖭⾡ᥦᑣㅫ⊩ᰃ〇 ᅮⱘˈ৺߭⿄ПЎϡ〇ᅮⱘDŽ
内部排序与外部排序根据在排序过程中待排序的 所有数据元素是否全部被放置在内存中,可将排序方 法分为内部排序和外部排序两大类。内部排序是指在 排序的整个过程中,待排序的所有数据元素全部被放 置在内存中;外部排序是指由于待排序的数据元素个 数太多,不能同时放置在内存,而需要将一部分数据 元素放置在内存,另一部分数据元素放置在外设上, 整个排序过程需要在内外存之间多次交换数据才能得 到排序的结果。本章只讨论常用的内部排序方法。 排序的基本方法内部排序主要有5种方法:插 入、交换、选择、归并和基数。 趟在排序过程中,基本动作执行一次。 西加大学数学与信息学院
ݙ䚼ᥦᑣϢ䚼ᥦᑣ ḍᥦᑣ䖛Ёᕙᥦᑣⱘ ᠔᭄᳝ܗ㋴ᰃ৺ܼ䚼㹿ᬒ㕂ݙᄬЁˈৃᇚᥦᑣᮍ ⊩ߚЎݙ䚼ᥦᑣ䚼ᥦᑣϸ㉏DŽݙ䚼ᥦᑣᰃᣛ ᥦᑣⱘᭈϾ䖛Ёˈᕙᥦᑣⱘ᠔᭄᳝ܗ㋴ܼ䚼㹿ᬒ 㕂ݙᄬЁ˗䚼ᥦᑣᰃᣛ⬅Ѣᕙᥦᑣⱘ᭄ܗ㋴Ͼ ᭄ˈϡ㛑ৠᯊᬒ㕂ݙᄬˈ㗠䳔㽕ᇚϔ䚼ߚ᭄ ܗ㋴ᬒ㕂ݙᄬˈϔ䚼ߚ᭄ܗ㋴ᬒ㕂䆒Ϟˈ ᭈϾᥦᑣ䖛䳔㽕ݙᄬП䯈Ѹᤶ᭄ᠡ㛑ᕫ ࠄᥦᑣⱘ㒧ᵰDŽᴀゴা䅼䆎ᐌ⫼ⱘݙ䚼ᥦᑣᮍ⊩DŽ ᥦᑣⱘᴀᮍ⊩ ݙ䚼ᥦᑣЏ㽕᳝5⾡ᮍ⊩˖ᦦ ܹǃѸᤶǃ䗝ᢽǃᔦᑊ᭄DŽ 䍳 ᥦᑣ䖛Ёˈᴀࡼᠻ㸠ϔDŽ
排序算法的效率评价排序算法的效率主要有两 点:一是在数据量规模一定的条件下,算法执行所消 耗的平均时间,对于排序操作,时间主要消耗在关键 字之间的比较和数据元素的移动上,因此我们可以认 为高效率的排序算法应该是尽可能少的比较次数和尽 可能少的数据元素移动次数;二是执行算法所需要的 辅助存储空间,辅助存储空间是指在数据量规模一定 的条件下,除了存放待排序数据元素占用的存储空间 之外,执行算法所需要的其他存储空间,理想的空间 效率是算法执行期间所需要的辅助空间与待排序的数 据量无关。 西加大学数学与信息学院
ᥦᑣㅫ⊩ⱘᬜ⥛ 䆘Ӌᥦᑣㅫ⊩ⱘᬜ⥛Џ㽕᳝ϸ ⚍˖ϔᰃ᭄䞣㾘ϔᅮⱘᴵӊϟˈㅫ⊩ᠻ㸠᠔⍜ 㗫ⱘᑇഛᯊ䯈ˈᇍѢᥦᑣ᪡ˈᯊ䯈Џ㽕⍜㗫݇䬂 ᄫП䯈ⱘ↨䕗᭄ܗ㋴ⱘ⿏ࡼϞˈℸ៥Ӏৃҹ䅸 Ў催ᬜ⥛ⱘᥦᑣㅫ⊩ᑨ䆹ᰃሑৃ㛑ᇥⱘ↨䕗᭄ሑ ৃ㛑ᇥⱘ᭄ܗ㋴⿏ࡼ᭄˗Ѡᰃᠻ㸠ㅫ⊩᠔䳔㽕ⱘ 䕙ࡽᄬټぎ䯈ˈ䕙ࡽᄬټぎ䯈ᰃᣛ᭄䞣㾘ϔᅮ ⱘᴵӊϟˈ䰸њᄬᬒᕙᥦᑣ᭄ܗ㋴ऴ⫼ⱘᄬټぎ䯈 Пˈᠻ㸠ㅫ⊩᠔䳔㽕ⱘ݊Ҫᄬټぎ䯈ˈ⧚ᛇⱘぎ䯈 ᬜ⥛ᰃㅫ⊩ᠻ㸠ᳳ䯈᠔䳔㽕ⱘ䕙ࡽぎ䯈Ϣᕙᥦᑣⱘ᭄ 䞣᮴݇DŽ
待排序记录序列的存储结构待排序记录序列可以 用顺序存储结构和和链式存储结构表示。在本章的讨 论中(除基数排序外),我们将待排序的记录序列用 顺序存储结构表示,即用一维数组实现。其定义如下 所示: # define maX num80待排序记录序列中的最大数 据元素个数 typedef struct elemtype{∥待排序的数据元素类型 keytype key;/数据元素的关键字 anytype otheritem;/(数据元素中的其他成份 ) Data Type MAX NUM+l; 西加大学数学与信息学院
ᕙᥦᑣ䆄ᔩᑣ߫ⱘᄬټ㒧ᵘ ᕙᥦᑣ䆄ᔩᑣ߫ৃҹ ⫼乎ᑣᄬټ㒧ᵘ䫒ᓣᄬټ㒧ᵘ㸼⼎DŽᴀゴⱘ䅼 䆎Ё˄䰸᭄ᥦᑣ˅ˈ៥Ӏᇚᕙᥦᑣⱘ䆄ᔩᑣ߫⫼ 乎ᑣᄬټ㒧ᵘ㸼⼎ˈे⫼ϔ㓈᭄㒘ᅲ⦄DŽ݊ᅮНབϟ ᠔⼎˖ #define MAX_NUM 80 //ᕙᥦᑣ䆄ᔩᑣ߫Ёⱘ᳔᭄ ㋴Ͼ᭄ܗ typedef struct elemtype { //ᕙᥦᑣⱘ᭄ܗ㋴㉏ൟ keytype key; //᭄ܗ㋴ⱘ݇䬂ᄫ anytype otheritem; //᭄ܗ㋴Ёⱘ݊Ҫ៤ӑ }DataType[MAX_NUM+1];
8.2插入排序 插入排序的主要思路是不断地将待排序的数值插 入到有序段中,使有序段逐渐扩大,直至所有数值都 进入有序段中位置 8.2.1直接插入排序 直接插入排序的基本思想 西加大学数学与信息学院
8.2 ᦦܹᥦᑣ ᦦܹᥦᑣⱘЏ㽕ᗱ䏃ᰃϡᮁഄᇚᕙᥦᑣⱘ᭄ؐᦦ ܹࠄ᳝ᑣ↉ЁˈՓ᳝ᑣ↉䗤⏤ᠽˈⳈ㟇᠔᭄᳝ؐ䛑 䖯ܹ᳝ᑣ↉Ёԡ㕂DŽ 8.2.1 Ⳉᦦܹᥦᑣ 1. Ⳉᦦܹᥦᑣⱘᴀᗱᛇ
直接插入排序是一种比较简单的排序方法。它的 基本思想是依次将记录序列中的每一个记录插入到有 序段中,使有序段的长度不断地扩大。其具体的排序 过程可以描述如下:首先将待排序记录序列中的第 个记录作为一个有序段,将记录序列中的第二个记录 插入到上述有序段中形成由两个记录组成的有序段, 再将记录序列中的第三个记录插入到这个有序段中, 形成由三个记录组成的有序段,…依此类推,每一趟 都是将一个记录插入到前面的有序段中,假设当前欲 处理第个记录,则应该将这个记录插入到由前1个记 录组成的有序段中,从而形成一个由个记录组成的按 关键字值排列的有序序列,直到所有记录都插入到有 序段中。一共需要经过n1趟就可以将初始序列的n个 记录重新排列成按关键字值大小排列的有序序列 西加大学数学与信息学院
Ⳉᦦܹᥦᑣᰃϔ⾡↨䕗ㅔऩⱘᥦᑣᮍ⊩DŽᅗⱘ ᴀᗱᛇᰃձᇚ䆄ᔩᑣ߫Ёⱘ↣ϔϾ䆄ᔩᦦܹࠄ᳝ ᑣ↉ЁˈՓ᳝ᑣ↉ⱘ䭓ᑺϡᮁഄᠽDŽ݊ԧⱘᥦᑣ 䖛ৃҹᦣ䗄བϟ˖佪ܜᇚᕙᥦᑣ䆄ᔩᑣ߫Ёⱘϔ Ͼ䆄ᔩЎϔϾ᳝ᑣ↉ˈᇚ䆄ᔩᑣ߫ЁⱘѠϾ䆄ᔩ ᦦܹࠄϞ䗄᳝ᑣ↉Ёᔶ៤⬅ϸϾ䆄ᔩ㒘៤ⱘ᳝ᑣ↉ˈ ݡᇚ䆄ᔩᑣ߫ЁⱘϝϾ䆄ᔩᦦܹࠄ䖭Ͼ᳝ᑣ↉Ёˈ ᔶ៤⬅ϝϾ䆄ᔩ㒘៤ⱘ᳝ᑣ↉ˈ«ձℸ㉏ˈ↣ϔ䍳 䛑ᰃᇚϔϾ䆄ᔩᦦܹࠄࠡ䴶ⱘ᳝ᑣ↉Ёˈ؛䆒ᔧࠡ℆ ໘⧚iϾ䆄ᔩˈ߭ᑨ䆹ᇚ䖭Ͼ䆄ᔩᦦܹࠄࠡ⬅i-1Ͼ䆄 ᔩ㒘៤ⱘ᳝ᑣ↉ЁˈҢ㗠ᔶ៤ϔϾ⬅iϾ䆄ᔩ㒘៤ⱘᣝ ݇䬂ᄫؐᥦ߫ⱘ᳝ᑣᑣ߫ˈⳈࠄ᠔᳝䆄ᔩ䛑ᦦܹࠄ᳝ ᑣ↉ЁDŽϔ݅䳔㽕㒣䖛n-1䍳ህৃҹᇚ߱ྟᑣ߫ⱘnϾ 䆄ᔩ䞡ᮄᥦ߫៤ᣝ݇䬂ᄫؐᇣᥦ߫ⱘ᳝ᑣᑣ߫DŽ
2.直接插入排序算法 将第i个记录插入到由前面i-1个记录构成的有序段 中主要有两个步骤: (1)将待插入记录叫保存在a0中,即a0=a(i; (2)搜索插入位置: j=i-;/最初指示i的前一个位置 while(a[0. key <ajj. key) a+1]=aj;:〃后移关键字值大于a|0key的记录 j=j1;∥将指向前一个记录,为下次比较做准备 [+1]=a0;/将a0放置在第计1个位置上 西加大学数学与信息学院
2. Ⳉᦦܹᥦᑣㅫ⊩ ᇚiϾ䆄ᔩᦦܹࠄࠡ⬅䴶i-1Ͼ䆄ᔩᵘ៤ⱘ᳝ᑣ↉ ЁЏ㽕᳝ϸϾℹ偸˖ Ł ᇚᕙᦦܹ䆄ᔩa[i] ֱᄬa[0]Ёˈेa[0]=a[i]; ł ᧰㋶ᦦܹԡ㕂˖ j=i-1; //j᳔߱ᣛ⼎iⱘࠡϔϾԡ㕂 while (a[0].key <a[j].key) { a[j+1]=a[j]; //ৢ⿏݇䬂ᄫؐѢa[0].keyⱘ䆄ᔩ j=j-1; //ᇚjᣛࠡϔϾ䆄ᔩˈЎϟ↨䕗ޚخ } a[j+1]=a[0]; //ᇚa[0]ᬒ㕂j+1Ͼԡ㕂Ϟ
完整的插入排序算法为: void insertsort(Data Type a, int n for(=2;i<=n;i+)/需要n-1趟 0=al;/.a(赋予监视哨 jF=l-1; whi(a0key<aj]key)/搜索插入位置 i atl=all; j=j-1; a+1=a|0];∥将原a中的记录放入第计+1个位置 西加大学数学与信息学院
ᅠᭈⱘᦦܹᥦᑣㅫ⊩Ў˖ void insertsort (DataType a, int n) { for (i=2; i<=n; i++) //䳔㽕n-1䍳 { a[0]=a[i]; //ᇚa[i]䌟ќⲥ㾚઼ j=i-1; while (a[0].key<a[j].key) //᧰㋶ᦦܹԡ㕂 { a[j+1]=a[j]; j=j-1; } a[j+1]=a[0]; // ᇚॳa[i]Ёⱘ䆄ᔩᬒܹj+1Ͼԡ㕂 } }