冒泡排序想必大家都非常熟悉了,这里就直接贴代码了
void BubbleSort(int array[],int len)
{
assert(array && len>0 );
for(int i = 0; i < len-1; ++i)
{
int flag = 1;
for(int j = 0; j < len-1-i; ++j)
{
if(array[j] > array[j+1])
{
swap(array[j], array[j+1]);
flag = 0;
}
}
if(flag == 1)
break;
}
}
时间复杂度为O(N*N),最好的情况下:优化后正序有序为O(n),稳定的算法。
没有优化的与原始序列的状态无关,优化后与原始序列的状态有关
- 快排
挖坑法
双指针法
//paration版本一:挖坑法
int Paration(int array[], int left, int right)
{
int key = array[right];
while(left < right)
{
while((left < right)&&(array[left] <= key) )
{
left++;
}
swap(array[left], array[right]);
while((left < right) && (array[right] >= key))
{
right--;
}
swap(array[left], array[right]);
}
return left;
}
//paration版本二:双指针法
int Paration2(int array[], int left, int right)
{
int key = array[right];
int pcur = left;
int pre = pcur-1;
while(pcur <= right)
{
if((array[pcur] <= key) && (++pre != pcur) )
{
swap(array[pcur], array[pre]);
}
++pcur;
}
return pre;
}
void QuickSort(int array[], int left ,int right)
{
assert(array);
if(left < right)
{
int index = Paration2(array, left ,right);
QuickSort(array, left, index-1);
QuickSort(array, index+1, right);
}
}
非递归实现:
void QuickSort2(int array[], int left, int right)
{
stack<int> s;
s.push(right);
s.push(left);
while(!s.empty())
{
int left = s.top();
s.pop();
int right = s.top();
s.pop();
if(left < right) //防止下面插入index+1, inex-1越界。
{
int mid = (left+right)/2;
int index = Paration2(array, left, right);
s.push(right);
s.push(index+1);
s.push(index-1);
s.push(left);
}
}
}
优化:
1)三数取中法
2)当区间已经划分到很小的时候可以改用插入排序
3)尾递归减少递归次数
//三数取中法,防止取到极端数据
int Middle(int array[], int left, int mid, int right)
{
if(array[left] > array[right])
{
if(array[right] > array[mid])
return right;
else if(array[left] > array[mid])
return mid;
else
return left;
}
else
{
if(array[right] < array[mid])
return right;
else if(array[left] < array[mid])
return mid;
else
return left;
}
}
//paration版本二:双指针法
int Paration2(int array[], int left, int right)
{
int mid = (left+right)/2;
int pos = Middle(array, left, mid, right);
swap(array[pos], array[right]);
int key = array[right];
int pcur = left;
int pre = pcur-1;
while(pcur <= right)
{
if((array[pcur] <= key) && (++pre != pcur) )
{
swap(array[pcur], array[pre]);
}
++pcur;
}
return pre;
}
void InsertSort(int array[], int size)
{
for(int i = 1; i < size; ++i)
{
int temp = array[i];
int end = i-1;
while(end>=0 && array[end] > temp)
{
array[end+1] = array[end];
end--;
}
array[end+1] = temp;
}
}
void QuickSort(int array[], int left ,int right)
{
assert(array);
while(right-left > 5) //使用尾部递归
{
int index = Paration2(array, left ,right);
QuickSort(array, left, index-1);
left = index+1;
}
if(right-left <= 5) //当分成很小的区间时,插入排序效率更高。
{
InsertSort(array+left, right-left+1);
}
}
时间复杂度为O(n*lgn),最好情况为O(n*lgn),最坏情况O(n*n),因为递归空间复杂度O(lgn)
不稳定的算法
最坏的情况下:基本有序时,退化为冒泡排序,几乎要比较N*N次,故为O(N*N)
它的应用场景是大规模的数据排序
快速排序算法的实际执行性能依赖与切分是否均衡,当正好把数组从中间”切开”时,
快速排序的实际性能最好。
切分越不均衡快速排序的实际性能就越差,
最坏情况下(第一次选取的切分元素是数组里最小的,第二次的切分元素是第二小的…)
算法的时间复杂度会退化到O(n^2)。