选择排序是一种简单但却效率低的算法,基本思想是:从待排序数组中选择最小(或最大)元素,将其放置在数组的起始位置,然后再从剩余的未排序部分中选择出最小(或最大)元素放置到已排序部分的末尾,直到数组中所有元素都有序为止。
1.简单选择排序
基本思想是:每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止。
说白了就是,一个序列,把第一个元素设为最小min,然后从其后面的元素开始搜索比min小且最小的元素,将其替换;再min+1,即后移一位,再进行比较,直到min=n-1为止,完成排序。
typedef int Elemtype;
void SelectSort(Elemtype arr[],int n)
{
for(int i=0;i<n-1;i++)
{
int min=i;
for(int j=i+1;j<n;j++)//搜索小于min的最小元素
{
if(arr[min]<arr[j])//找到比min晓得元素就将min指向这个元素
min=j;
}
if(min!=i)
swap(arr[i],arr[min]);
}
}
空间效率:空间复杂度为O(1)。
时间效率:时间复杂度为O(n^2)。
2.堆排序
堆排序说白了就是,将一个待排序的数组看作一个完全二叉树,采用大根堆的形式构造这个二叉树,此时根节点就是整个数组的最大值,然后将最大值与最后一个值交换(此时的最大值不再参与排序),交换后堆的排序混乱,重新构建堆;然后将此时的根节点也后移(但在前一个最大值之前),再重新构建堆;重复至堆只剩一个元素,完成排序。
基本思路:
将待排序的序列构建成一个大根堆或小根堆。
将堆顶元素与堆底元素交换。
对剩余的元素重新构建堆。
重复步骤2和3,直到整个序列有序。
void Adjust(int *arr,int i,int length) //调整一个堆,形成大根堆
{
int left=2*i+1; //左子节点下标
int right=2*i+2; //右子节点下标
int max=i; //初始化,假设左右孩子的父节点就是最大值
if(left<length && arr[left]>arr[max]) //左子节点比最大节点大
max=left;
if(right<length && arr[right]>arr[max]) //右子节点比最大节点大
max=right;
if(max!=i)
{ //若最大值max已经发生变化,则交换值,把最大的值放到根节点
swap(arr[max],arr[i]);
Adjust(arr,max,length); //递归,使其子树也为堆
}
}
void HeapSort(int *arr,int length) //堆排序
{
for(int i=length/2-1;i>=0;i--) //从最后一个非叶子节点开始向上遍历,建立大根堆
Adjust(arr,i,length);
for(int j=length-1;j>0;j--) //调整序列,注意此时要将堆看成序列
{
swap(arr[0],arr[j]); //将第一个值与最后的值交换,就是将最大值移到后面
Adjust(arr,0,j); //因为每交换一次之后,就把最大值拿出(不再参与调整堆),第三个参数应该写j而不是length
}
}
空间效率:空间复杂度为O(1)。
时间效率:时间复杂度为O(Nlog2N)。