题目:长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他书的swap,请设计并实现排序。
未排序的元素永远不会指向已排序的元素的位置。比如a[2]=2时,绝对不会存在有a[i]=2, i!=2的情况。
本来想用类似快排的方法,一次排好一个元素,然后分开,但是不知道怎么出错了,代码被我注释了,这里采用简单粗暴的实现方式——一个已连续排序计数器,计数器达到N就是排好序了;碰到没有排序的就交换,然后计数器清零;碰到排好序的就计数器加①。
其实可以每次交换的时候把下标放进一个容器(hash?),然后下次交换可以直接省略比较;
或者每次从未排序的下标中抽取一个swap,然后把swap好的下标从容器中移除。
欢迎指正:
#include <iostream>
using namespace std;
int pos = -1;
// change a[i] with 0
void swap(int *arr, int i){
if (pos == -1)
while(arr[++pos]!=0){}
arr[pos] = arr[pos] ^ arr[i];
arr[i] = arr[pos] ^ arr[i];
arr[pos] = arr[pos] ^ arr[i];
pos = i;
}
// put a[i] at i: if a[a[i]] is not 0, swap once; else swap twice.
int zeroswap(int *arr, int i){
int temp = arr[i];
if (arr[i]==pos)
swap(arr, i);
else {
swap(arr, arr[i]);
swap(arr, i);
}
return temp;
}
void print(int *arr, int start, int end){
for(int i = start; i <=end; i++)
cout << arr[i] << " ";
cout << endl;
}
// void partition(int *arr, int start, int end){
// while(start<end && arr[start]==start) start++;
// while(end>start && arr[end]==end) end--;
// if(start<end){
// int ok = zeroswap(arr, start);
// if(ok>=start&&ok<=end){
// int left = ok - 1;
// int right = ok + 1;
// if(left>=start)
// partition(arr, start, left);
// if(right<=end)
// partition(arr, right, end);
// }
// else if(ok>end){
// partition(arr, start, end);
// partition(arr, end, ok-1);
// }else{
// partition(arr, ok+1, start);
// partition(arr, start, end);
// }
// }
// else if(start==end)
// if (arr[start]!=start)
// zeroswap(arr, start);
// }
void sort(int *arr, int size){
int num = 0;
int index = 0;
while(num!=size){
if(arr[index]==index)
num++;
else{
zeroswap(arr, index);
num=0;
}
if(index==size-1)
index=0;
else
index++;
}
}
int main(){
int arr[] = {9, 11, 1, 3, 10, 8, 17, 0, 13, 12, 5, 14, 4, 7, 16, 6, 2, 19, 15, 18};
sort(arr, 20);
print(arr, 0, 19);
}