排序 选择排序&&堆排序
Posted AIL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序 选择排序&&堆排序相关的知识,希望对你有一定的参考价值。
选择排序&&堆排序
1.选择排序:
介绍:选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
步骤:假设数组array长度为N即有数组内有N个数据未排序数据
1.第一趟遍历将这N个数据中最小的数据和array[0]交换。
2.第二趟则遍历N-1个数据,将这N-1个数据中最小的和array[1]交换(第二趟中的数组是从原数组中的array[1]开始即排除第一趟中最小的数据再进行交换)。
...
程序实现:
方法1:每趟选择最小数据进行交换
1 void SelectSort(int* _array, size_t _arraySize) 2 { 3 assert(_array&&_arraySize); 4 for (size_t i = 0;i < _arraySize;++i) 5 { 6 int MinIndex = i;//记录首位置下标 7 for (size_t j = i + 1;j < _arraySize;++j) 8 { 9 if (_array[MinIndex] > _array[j])//比较首位置之后的各个元素并将最小数据的下标赋给MinIndex 10 MinIndex = j; 11 } 12 //if (MinIndex != i)//防止首元素即最小时进行交换,减少不必要开销 13 swap(_array[MinIndex], _array[i]); 14 } 15 return; 16 }
方法2:与方法一类似,进行了优化,每趟将最小数据置首,将最大元素置尾
1 void SelectSort_optimize(int* _array, int _arraySize) 2 { 3 assert(_array&&_arraySize); 4 5 int left = 0; 6 int right = _arraySize - 1; 7 for (;left <= right;++left,--right)//每一趟找到最大值和最小值减少循环次数 8 { 9 int MinIndex = left; 10 int MaxIndex = right; 11 for (int index = left;index <= right;++index)//此时数组为闭区间,与未优化时存在差异 12 { 13 if (_array[MinIndex] > _array[index]) 14 MinIndex = index; 15 if (_array[MaxIndex] < _array[index]) 16 MaxIndex = index; 17 } 18 if (left != MinIndex) 19 { 20 swap(_array[left], _array[MinIndex]); 21 if (left == MaxIndex)//避免如果最大值为_array[left]时,将被上一步操作移到_array[MinIndex]后出错 22 MaxIndex = MinIndex;//将MaxIndex更新 23 } 24 if (right != MaxIndex) 25 swap(_array[right], _array[MaxIndex]); 26 } 27 return; 28 }
效率分析:
算法稳定性:不稳定
时间复杂度:O(n^2)
空间复杂度:O(1)
2.堆排序
介绍:堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大堆和小堆,是完全二叉树。升序排序时使用大堆,降序排序时使用小堆。
步骤:对数组_array进行升序排序,假设数组array长度为N即有数组内有N个数据未排序数据
1:将_array中的N个数据构成大堆后,此时最大值即为_array[0],然后将_array[0]与_array[N-1]交换。
2:除_array[N-1]外,其余数据继续建立大堆后,此时最大值仍为_array[0],然后将_array[0]与_array[N-2]交换。
...
根据下面网址演示可以清楚理解堆排序的过程
http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/heap_sort.asp
程序实现:
1 void AdjustDown(int* _arr,size_t ParIndex,int _arrSize)//从父节点开始向下调整 2 { 3 size_t ChildIndex = ParIndex * 2 + 1;//找出父节点的左子树下标 4 5 while (ChildIndex < _arrSize) 6 { 7 if ((_arr[ChildIndex] < _arr[ChildIndex + 1]) && ((ChildIndex + 1) < _arrSize))//找出父节点的左右子树中的较大值的下标 8 ChildIndex++; 9 if (_arr[ParIndex] < _arr[ChildIndex]) 10 { 11 swap(_arr[ParIndex], _arr[ChildIndex]);//如果父节点数据小于子节点数据则交换 12 ParIndex = ChildIndex; //继续调整交换后的子树,保证堆中任意子树均为大堆 13 ChildIndex = ParIndex * 2 + 1; 14 } 15 else//如果_arr[ParIndex] > _arr[ChildIndex]则说明其已经为大堆且子树也为大堆,跳出循环 16 break; 17 } 18 } 19 void HeapSort(int* _array, int _arraySize) 20 { 21 assert(_array&&_arraySize > 0); 22 //建堆 23 for (int i = _arraySize / 2 - 1;i >= 0;--i)//从最后一个非叶子节点开始向下调整直到根节点调整完 24 AdjustDown(_array, i, _arraySize); 25 26 for (int j = _arraySize - 1;j > 0;--j) 27 { 28 swap(_array[0], _array[j]); 29 AdjustDown(_array, 0,j); 30 } 31 return; 32 }
下面是当数组为{3,12,24,2,6}时的排序过程
效率分析:
算法稳定性:不稳定
时间复杂度:O(n^lg n)
空间复杂度:O(1)
以上是关于排序 选择排序&&堆排序的主要内容,如果未能解决你的问题,请参考以下文章