算法原理:
始终将两个序列分为两个部分:待排序前缀,有序后缀,且前缀不大于后缀。反复迭代,取出未排序数据中最大值,放入到有序序列最小的位置(最前端)。
不变形:任意时刻,前缀区间s[0,r]总小于等于后缀s(r,n),后缀s(r,n)总有序。
适应范围:向量或者链表等任何序列结构体
实际应用:
算法实现:
//列表的选择排序算法:从p开始的n个元素排序(valid(p)&&rank(p)+n<_size)
template <typename T>
void List<T>::selectionSort ( ListNodePtr p, int n )
{
ListNodePtr pHead = p->pred;//必须保存头指针,不然调用selectmax,会有可能把当前指针删除掉
ListNodePtr pBar = p;//有序区间标志,首节点
for (int i = 0; i < n; ++i)
{
pBar = pBar->succ;
}//有序区间置空,待排序空间为(pHead,pBar)
while (n > 1)//至少两个有效数据
{
ListNodePtr maxpnode = selectMax(pHead->succ, n);//第一个参数要用pHead的下一个节点
T maxdata = remove(maxpnode);//从无序区间删除
insertBefore(pBar,maxdata);//添加到有序区间,并作为首节点
pBar = pBar->pred;//移动有序区间首节点位置
n--;
}
}
需要解释的是,查找算法,找到的是无序前缀中的最大值。
template <typename T>//p开始的n个节点
ListNodePtr List<T>::selectMax(ListNodePtr p,int n) const
{
ListNodePtr pCur = p;
ListNodePtr pMax = p;//将当前节点定为最大节点
while (n > 1)
{
pCur = pCur->succ;//也可以放在if判断之后,但是多了依次跟自己比较.n>1不包含本身
if (pMax->data < pCur->data)
{
pMax = pCur;
}
n--;
}
return pMax;
}
算法分析:
算法名称 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡 | O() | O() | O() | 0(1) | 不稳定 |
算法时间复杂度:
n + (n-1) + (n-2) + ...+2+1
算法优化:
属于CBA算法。selectMax算法从O(n)可以优化为O(logn),整体算法下降为O(nlogn)