[排序算法] 选择排序(2种)

1.直接选择排序

【思想】选出剩下的未排序数据中的最小元素与第i个元素交换

【特点】不稳定

 空间代价:O(1)

 时间代价:O(n^2)

 1 void SelectSort(int Array[], int n)
 2 {
 3     // 依次选出第i小的记录,即剩余记录中最小的那个
 4     for (int i=0; i< n - 1; i ++)
 5     {
 6         // 首先假设记录i就是最小的
 7         int Min = i;
 8         // 开始向后扫描所有剩余记录
 9         for (int j = i + 1; j < n; j++)
10             // 如果发现更小的记录,记录它的位置
11             if (Array[j] < Array[Min])
12                 Min = j;
13         //将第i小的记录放在数组中第i个位置
14         swap(Array[i], Array[Min]);
15     }
16 }

2.堆排序

【思想】基于最大推来实现,效率更高。堆排序的基本思想是:首先将n个记录按关键码建成堆(初始堆),将堆顶元素与最后一个元素交换,然后将剩余的元素调整成堆...如此反复,便得到了一个按关键码有序的序列。

可参考我整理的最大堆的类实现http://www.cnblogs.com/lca1826/p/6590864.html

【特点】不稳定

 空间代价:O(1)

 时间代价:O(nlogn)

 1 /*
 2 堆排序
 3 (1)用大根堆排序的基本思想
 4  ① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
 5  ② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,
 6     由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
 7  ③ 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。
 8     然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,
 9     由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n- 2].keys≤R[n-1..n].keys,
10     同样要将R[1..n-2]调整为堆。
11     ……
12     直到无序区只有一个元素为止。
13 
14 (2)大根堆排序算法的基本操作:
15  ① 初始化操作:将R[1..n]构造为初始堆;
16  ② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
17 
18  注意:
19  ①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。
20  ②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。
21    堆排序和直接选择排序相反:在任何时刻,堆排序中无序区总是在有序区之前,
22    且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。
23 */
24 #include <iostream>
25 using namespace std;
26 
27 void HeapAdjust(int SortData[],int StartIndex, int Length)
28 {
29     int MaxChildIndex = 2*StartIndex + 1;
30     while(MaxChildIndex < Length)
31     {
32         //比较左子树和右子树,记录最大值的j
33         if((MaxChildIndex < Length - 1) && (SortData[MaxChildIndex] < SortData[MaxChildIndex + 1])){
34             MaxChildIndex ++;
35         }
36         if(SortData[StartIndex] < SortData[MaxChildIndex])
37         {
38             //交换i与j位置的数据
39             int temp = SortData[StartIndex];
40             SortData[StartIndex] = SortData[MaxChildIndex];
41             SortData[MaxChildIndex] = temp;
42             //堆被破坏,重新调整
43             StartIndex = MaxChildIndex;
         MaxChildIndex = 2*StartIndex + 1;
44 } 45 else break; 46 } 47 return; 48 } 49 50 //堆排序 51 void HeapSortData(int SortData[], int Length) 52 { 53 int i=0; 54 55 //将SortData[0,Lenght-1]建成大根堆 56 for (i=Length/2-1; i>=0; i--) 57 { 58 HeapAdjust(SortData, i, Length); 59 } 60 61 for (i=Length-1; i>0; i--) 62 { 63 //与最后一个记录交换 64 int tmpData =SortData[0]; 65 SortData[0] =SortData[i]; 66 SortData[i] =tmpData; 67 //将SortData[0..i-1]重新调整为大根堆 68 HeapAdjust(SortData, 0, i); 69 } 70 return; 71 } 72 73 int main() 74 { 75 int array[6] = {10, 15, 56, 25, 30, 70}; 76 HeapSortData(array, 6); 77 for (int index = 0; index != 6; ++index) 78 { 79 cout<<array[index]<<" "; 80 } 81 cout<<endl; 82 return 0; 83 }

 

转载于:https://www.cnblogs.com/lca1826/p/6486261.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值