选择排序事实上是对冒泡排序的改进,每次只选择前n个元素中最大的一个与无序部分的最后位置元素交换,将冒泡排序中n次的交换减少至1次。
本部分基于双链表实现,首先来看一下双链表的建立过程。
typedef struct node2 {
int value;
struct node2* before;
struct node2* after;
}node2;
void create_list2(int n, node2* head, node2* tail) {
head->before = NULL;
head->after = tail;
tail->before = head;
tail->after = NULL;
node2* last = tail;
while (n--) {
node2* temp = (node2*)malloc(sizeof(node2));
temp->value = 10-n;
head->after = temp;
temp->before = head;
temp->after = last;
last->before = temp;
last = last->before;
}
}
之所以选用双链表,是因为可以快速的定位无序部分的最后一个元素位置,方便交换数据。在此基础上,我们再来看选择排序的实现过程:
void selectsort(node2* head, node2* tail) {
node2* pos = tail->before;
while (pos->before != head)
{
node2* temp = head->after;
node2* max = temp;
while (temp != pos)
{
temp = temp->after;
if ((max->value) <= (temp->value))
max = temp;
}
swap(pos->value,max->value);
pos = pos->before;
}
}
由上述代码可以看到,算法的复杂度依旧是n^2,但是由于交换次序的减少,对于冒泡排序来说,也已经是个不小的改进。其中值得注意的一点是,交换时,用的是小于等于,而不是小于,是因为,要保证算法的稳定性,即如果两个元素大小相同,那么排序过后,本来在后面的元素还应该在后面。