一、快速排序的基本思想
设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解:
在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
注意:
划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
其中low≤pivotpos≤high。
②求解:
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。
完整的代码如下:
#include
#include
using namespace std;
int partition(int *arr , int low , int high)
{
int pivo = arr[low];
while(low < high)
{
while(low < high && arr[high] >= pivo)
--high;
arr[low] = arr[high];
while(low < high && arr[low] <= pivo)
++low;
arr[high] = arr[low];
}
arr[low] = pivo;
return low;
}
// 快速排序 递归
void qsort(int *arr , int low , int high)
{
if(low < high)
{
int pivo = partition(arr , low , high);
qsort(arr , low , pivo-1);
qsort(arr , pivo+1 , high);
}
}
// 快速排序 非递归
void qsort_no_recursive(int *arr , int low , int high)
{
stacks;
int pivo;
if(low < high)
{
pivo = partition(arr , low , high);
if(low < pivo - 1)
{
s.push(low);
s.push(pivo-1);
}
if(pivo + 1 < high)
{
s.push(pivo+1);
s.push(high);
}
while(!s.empty())
{
high = s.top();
s.pop();
low = s.top();
s.pop();
pivo = partition(arr , low , high);
if(low < pivo - 1)
{
s.push(low);
s.push(pivo-1);
}
if(pivo + 1 < high)
{
s.push(pivo+1);
s.push(high);
}
}//while
}//if
}
//简单示例
int main(void)
{
int i , a[11] = {20,11,12,5,6,13,8,9,14,7,10};
printf("排序前的数据为:\n");
for(i = 0 ; i < 11 ; ++i)
printf("%d ",a[i]);
printf("\n");
//qsort(a , 0 , 10);
qsort_no_recursive(a , 0 , 10);
printf("排序后的数据为:\n");
for(i = 0 ; i < 11 ; ++i)
printf("%d ",a[i]);
printf("\n");
return 0;
}
二、希尔排序
#include
using namespace std;
void shell_sort(int array[] , int length)
{
int i , j , temp;
int d = length/2; // 设置希尔排序的初始增量
while(d >= 1)
{
for(i = d ; i < length ; ++i)
{
temp = array[i];
j = i - d; // 步长为d的前面一个位置
while(j >= 0 && array[j] > temp) // 从后往前进行插入排序
{
array[j + d] = array[j];
j -= d;
}
array[j + d] = temp; // 找到了插入位置
}
d /= 2;
}
}
int main(void)
{
int i , a[]={25,19,6,58,34,10,7,98,160,0};
shell_sort(a , 10);
for(i = 0 ; i < 10 ; ++i)
cout< void ShellSort(T *a,int len) //希尔排序算法
{
int gap , j;
for(gap = len / 2 ; gap > 0 ; gap /= 2)
{
for(j = gap;j < len ; ++j) //j从gap个元素开始
{
if(a[j] < a[j - gap]) //每个元素与自己组内的数据进行直接插入排序
{
T temp = a[j];
int k = j - gap;
while(k >= 0 && a[k] > temp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = temp;
}
}
}
}
三、插入排序
void InsertSort(int array[] , int length) // 无哨兵的插入排序
{
int i , j , temp;
for(i = 1 ; i < length ; ++i)
{
if(array[i] < array[i-1])
{
temp = array[i];
for(j = i - 1 ; j >= 0 && array[j] > temp ;--j)
array[j + 1] = array[j];
array[j + 1] = temp;
}
}
}
void InsertSort(int array[] , int length) // 有哨兵的插入排序
{
int i , j ;
for(i = 1 ; i <= length ; ++i)
{
if(array[i] < array[i-1])
{
array[0] = array[i];
for(j = i - 1 ; array[j] > array[0] ;--j)
array[j + 1] = array[j];
array[j + 1] = array[0];
}
}
}
(1)时间、空间复杂度void SelectSort(int array[] , int length) // 简单选择排序
{
int i , j , k;
for(i = 0 ; i < length-1 ; ++i)
{
k = i;
for(j = i + 1 ; j < length ; ++j) // 从后面选择一个最小的记录
{
if(array[j] < array[k])
k = j;
}
if(k != i) // 与第i个记录交换
swap(array[i] , array[k]);
}
}
(1)关键字比较次数
void Merge(int array[] , int low , int mid , int high)
{
int i , j , k;
int *temp = (int *)malloc((high - low + 1)*sizeof(int));
i = low , j = mid + 1 , k = 0;
while(i <= mid && j <= high)
{
if(array[i] < array[j]) // 进行排序存入动态分配的数组中
temp[k++] = array[i++];
else
temp[k++] = array[j++];
}
while(i <= mid) // 如果前一半中还有未处理完的数据,按顺序移入动态分配的数组内
temp[k++] = array[i++];
while(j <= high) // 如果前一半中还有未处理完的数据,按顺序移入动态分配的数组内
temp[k++] = array[j++];
for(i = low , j = 0; i<= high ; ++i)
array[i] = temp[j++];
free(temp);
}
void Msort(int array[] , int low , int high)
{
int mid;
if(low < high)
{
mid = (low + high)>>1;
Msort(array , low , mid);
Msort(array , mid + 1 , high);
Merge(array , low , mid , high);
}
}
void HeapAdjust(int array[] , int s , int m) // 对堆进行调整,使下标从s到m的无序序列成为一个大顶堆
{
int j , temp = array[s];
for(j = 2*s; j <= m ; j *= 2)
{
if(j < m && array[j] < array[j + 1]) // 如果结点的左孩子小于右孩子增加j的值
++j; // 用于记录较大的结点的下标
if(temp >= array[j]) // 如果父结点大于等于两个孩子,则满足大顶堆的定义,跳出循环
break;
array[s] = array[j]; // 否则用较大的结点替换父结点
s = j; // 记录下替换父结点的结点下标
}
array[s] = temp; // 把原来的父结点移动到替换父结点的结点位置
}
void HeapSort(int array[] , int len)
{
int i;
for(i = len / 2; i >= 0 ; --i) // 建立大顶堆
HeapAdjust(array , i , len-1);
for(i = len - 1 ; i > 0 ; --i)
{
swap(array[0] , array[i] ); // 第个元素和最后一个元素进行交换
HeapAdjust(array , 0 , i-1); // 建立大顶堆
}
}
七、冒泡排序
// 将小元素冒泡到最前面,首先操作的是小元素
void Bubble_Sort1(int array[] , int len)
{
int i , j;
for(i = 0 ; i < len - 1 ; ++i)
{
for(j = i + 1 ; j < len ; ++j)
{
if(array[j] < array[i])
swap(array[i] , array[j] );
}
}
}
// 将最大的元素冒泡到最后面
void Bubble_Sort2(int array[] , int len)
{
int i , j;
for(i = 0 ; i < len ; ++i) //注意和上面的算法对照此循环
{
for(j = 0 ; j < len - 1 - i ; ++j)
{
if(array[j] > array[j + 1])
swap(array[j] , array[j+1] );
}
}
}
// 双向冒泡
void Bubble_Sort3(int array[] , int len)
{
int left , right , i;
left = 0 , right = len - 1;
while(left < right)
{
for(i = left ; i < right ; ++i) // 从左到右冒泡
{
if(array[i + 1] < array[i])
swap(array[i] , array[i+1]);
}
--right;
for(i = right ; i > left ; --i) // 从右到左冒泡
{
if(array[i ] < array[i - 1])
swap(array[i] , array[i-1]);
}
++left;
}
}