交换排序:
交换排序的分类:
冒泡排序
快速排序
1.冒泡排序:
思想:从数组的末尾元素开始比较两个元素的大小,然后根据大小换位置,直到将最大或最小的元素排到数组的起始位置;
代码实现如下:
void Swap(int *left,int* right){
in tmp=*left;
*left=*right;
*right=tmp;
}
void Bubblesort(int arr[],int size){
for(int bound=0;bound<size;++bound){
for(int cur=0;cur<size-1-bound;cur++){
if(arr[cur]>arr[cur+1]){
Swap(&arr[cur],&arr[cur+1});
}
}
}
}
int main(){
int array[]={9,5,2,4}
int size=sizeof(arr)/sizeof(arr[0]);
Bubblesort(array,size);
return 0;
}
2.快速排序:
思路:三大步:
第一步:确定一个基准值;
找基准值的方法:
1.选边上;
2.随机法;
3.三数取中法:区间最左边,区间最右边,选值是中间一个数;
(第二种和第三种方法需要把值交换到边上)
第二步:做分割:遍历整个数组区间,比较每个数和基准值的大小关系,遍历结束后让比基准值小的放大它左边,比基准值大的放到它右边(左边比基准值小,右边比基准值大)
关于做分割的具体三种方法:
1.Hover法(左右指针法/左右下标法)
//对数组中的[low,hight]的区间进行分组,基准值是array[low]
int Partition(int array[],int low,int hight){
int piove=array[low];
int begin=low;
int end=hight;
//[begin,end]的区间是没被比较过的数;
while(begin<end){
while(begin<end && array[begin]<=piove){
begin++;
}
while(begin<end && array[end]>=piove){
end--;
}
//array[begin]比基准值大了,交换begin和end下标处的数据;
Swap(array,begin,end);
}
//low基准值;
//[low+1,begin] 比基准值小;
//[begin+1,high] 比基准值大;
//把基准值和比他小的最后一个数进行交换;
Swap(array,low,begin);
return begin;
}
2.挖坑法:(通过来回填坑进行交换)
int Partition(int array[], int low, int high){
int pivot = array[low]; //begin 是坑的下标;
int begin = low; //从基准值的位置开始,而不是low+1;
int end = high;
//(begin,end)的区间是没有被比较过的数据;
while (begin < end){
//如果基准值在左边,需要从右边开始走;
while (begin<end && array[begin] <= pivot){
begin++;
}
//array[begin]比基准值大了,坑的下标是end;
//array[end] = array[begin];
//begin变为坑的下标;
while (begin<end && array[end] >= pivot){
end--;
}
//array[end]比基准值小了,坑的下标就是begin;
array[begin] = array[end];
//end是坑的下标;
}
//low基准值;
//[low+1,begin] 比基准值小;
//[begin+1,high] 比基准值大;
//最后把基准值填到最后一个坑;
array[begin] = pivot;
return begin;
}
3.前后指针法:
int Partition(int array[], int low, int high){
int d = low + 1;
int i = low + 1;
int pivot = array[low];
while (i <= high){
if (array[i] < pivot){
Swap(array,d,i);
d++;
}
i++;
}
Swap(array, d - 1, low);
return d - 1;
}
第三步:采用一个分治算法;按同样的方式,分别对同样两个小区间进行处理,直到分出来的小区间的长度个数 <= 1, 就可以停止;
快速排序算法的实现:
1.通过递归的方法进行查找:
int Partition(int array[],int low,int hight){
int piove=array[low];
int begin=low;
int end=hight;
while(begin<end){
while(begin<end && array[begin]<=piove){
begin++;
}
while(begin<end && array[end]>=poive){
end--;
}
array[begin]=array[end];
}
array[begin]=piove;
return begin;
}
void _QuickSort(int array[], int low, int high){
if (low == high){ //区间内只剩一个数,有序,所以不需要排序;
return;
}
if (low > high){
return; //区间内没有数,所以不需要排序;
}
//1.找基准值,选最左边,基准值得下标是low;
//2.遍历整个区间,把小的放左边,大的放右边,返回基准值所在下标;
int pivotIdx = Partition(array, low, high);
//3.区间被分为三部分:
//[low,pivotIdx-1] 小
//[pivotIdx,pivotIdx] 有序
//[pivotIdx+1,high] 大
//4.分治算法,分别调用两个小区间;
_QuickSort(array,low, pivotIdx - 1);
_QuickSort(array,pivotIdx + 1, high);
//直到区间长度为0,或区间长度为1,表示区间的数已经有序;
}
void QuickSort(int array[], int size){
_QuickSort(array, 0, size - 1);
}
2.非递归的快速排序:
#include <stack>
void QuickSortNoR(int array[], int size){
std::stack <int> stack;
stack.push(0); //low
stack.push(size - 1); //high
while (stack.empty()){
int high = stack.top();
stack.pop();
int low = stack.pop();
stack.pop();
if (low >= high){
continue;
}
int pivotIdx = Partition(array, low, high);
[low,pivotIdx-1]
stack.push(low);
stack.push(pivotIdx - 1);
[pivotIdx+1,high]
stack.push(pivotIdx + 1);
stack.push(high);
}
}