选择排序 稳定亦不稳定

1.题目

选择排序

2.数据结构与算法

algorithm:每次选择最大的元素放在末尾,以数值交换为基础完成该算法。
在这里插入图片描述

3.源代码

#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <list>
#include <algorithm>
using namespace std;

void selectionSort(list<int> &l){
	list<int>::iterator tail = l.end();
	list<int>::iterator head = l.begin();
	list<int>::iterator max, p;

	while(head != tail){
		//选择最大值
		max = head;
		p = head;
		while(p != tail){
			if(*p >= *max){
				max = p;
			}
			p++;
		}
		//最大值归位
		swap(*max, *(--tail));
	}
}


int main()
{
	srand(time(NULL));
	const int TEST_NUM = 100;
	
	//初始化有序列表
	list<int> l;
	for(int i = 0; i < TEST_NUM; i++){
		l.push_back(rand() % 10);
	}
	//遍历输出list
	cout<<"input:"<<endl;
	list<int>::iterator it;
	for (it=l.begin(); it!=l.end(); it++){
		cout<<*it<<" ";
	}

	selectionSort(l);

	//遍历输出list
	cout<<endl<<"output:"<<endl;
	for (it=l.begin(); it!=l.end(); it++){
		cout<<*it<<" ";
	}

 	return 0;
}

4.时间复杂度

算法稳定性:
为了维持选择排序算法的稳定性,对于相同元素,我们总是选择最右侧的为max进行归位。
在这里插入图片描述
但对于本算法来说,这并不足够,因为本算法是基于值交换的,并没有发挥list本身的优势,基于值交换的选择排序算法依然是不稳定的。
举个例子:关注4与4* 的相对位置
5 4* 4
4 4* 5
排序动作:交换了位置0与位置2的数值。所以在排序前与排序后,其相对次序发生了改变,所以这种情况下SelectionSort是不稳定排序算法。

但是基于list本身的特性实现的选择排序算法是稳定的。
举个例子
5 4* 4
4* 4 5
排序动作:将位置0的Node拆下来,插入到位置2的后面。这样的机制实现的算法才是稳定的选择排序算法。(清华 DSA 邓俊辉 书中所给需要额外delete和new,这个时间耗费其实也是得不偿失的,可以考虑自己写一个算法:修改两Node的前驱和后继来实现。这样即不需要delete与new的时间耗费,同时又能保证算法的稳定性。)

时间复杂度:整个算法呈算数级数,需要 ο ( n 2 ) \omicron(n^2) ο(n2)的复杂度。

除此之外,你可能会想到,如果max已经就位,就无需再进行swap操作,你的第一想法可能是用if语句进行判断。然而从概率的角度来讲,max直接就位,这种概率发生是极低的。如果加了if语句,只会得不偿失,以下给出证明。
在这里插入图片描述
证明:
在各元素独立分布的情况下,max就位的概率和为调和级数
1 / n + 1 / ( n − 1 ) + 1 / ( n − 2 ) + . . . + 1 / 2 + 1 = Θ ( l n ( n ) ) 1/n +1/(n-1) + 1/(n-2)+ ...+1/2 +1=\Theta(ln(n)) 1/n+1/(n1)+1/(n2)+...+1/2+1=Θ(ln(n))
就平均渐进意义上而言: Θ ( l n ( n ) ) / n → 0 \Theta(ln(n))/n\rightarrow0 Θ(ln(n))/n0
max直接就位,这种概率发生是极低的,使用if只会得不偿失。

5.结论

直接选择排序(SelectionSort)
1.基于list(转移结点)实现的SelectionSort是稳定的
2.基于值交换实现的SelectionSort是不稳定的
3.时间复杂度: ο ( n 2 ) \omicron(n^2) ο(n2)

如有错误,请您批评指正。
参考书籍:清华大学《数据结构(C++语言版)》(第三版) 邓俊辉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值