您的位置:首页 > 其它

排序算法总结

2016-02-22 14:59 232 查看
算法部分参考moreWindows的白话排序算法。

算法实现:

//换位函数
inline void Swap(int &a, int &b)
{
int c = a;
a = b;
b = c;
}

//排序算法之一:冒泡排序
//基本思想:
//设数组长度为N。
//1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。
//2.这样对数组的第0个数据到N - 1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N - 1个位置。
//3.N = N - 1,如果N不为0就重复前面二步,否则排序完成。

//冒泡排序1:定义
void BubbleSort1(int a[], int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 1; j < n - i; j++)
if (a[j - 1] > a[j])
Swap(a[j - 1], a[j]);
}

//冒泡排序2
//设置一个标志,如果这一趟发生了交换,则为true,否则为false。明显如果有一趟没有发生交换,说明排序已经完成。
void BubbleSort2(int a[], int n)
{
int j, k;
bool flag;
k = n;
flag = true;
while (flag)
{
flag = false;
for (j = 1; j < k; j++)
if (a[j - 1] > a[j])
{
Swap(a[j - 1], a[j]);
flag = true;
}
k--;
}
}

//冒泡排序3
//如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字,
//那么在第一趟遍历后,最后发生交换的位置必定小于10,且这个位置之后的数据必定已经有序了,
//记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。
void BubbleSort3(int a[], int n)
{
int j, k;
int flag;
flag = n;
while (flag > 0)
{
k = flag;
flag = 0;
for (j = 1; j < k; j++)
if (a[j - 1] > a[j])
{
Swap(a[j - 1], a[j]);
flag = j;
}
}
}

//排序算法之二:插入排序
//基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面
//已经排好序的子序列中的适当位置,直到全部记录插入完成为止。

//设数组为a[0…n - 1]。
//1. 初始时,a[0]自成1个有序区,无序区为a[1..n - 1]。令i = 1
//2. 将a[i]并入当前的有序区a[0…i - 1]中形成a[0…i]的有序区间。
//3. i++并重复第二步直到i == n - 1。排序完成。

//插入排序1:定义
void Insertsort1(int a[], int n)
{
int i, j, k;
for (i = 1; i < n; i++)
{
//为a[i]在前面的a[0...i-1]有序区间中找一个合适的位置
for (j = i - 1; j >= 0; j--)
if (a[j] < a[i])
break;
//如找到了一个合适的位置
if (j != i - 1)
{
//将比a[i]大的数据向后移
int temp = a[i];
for (k = i - 1; k > j; k--)
a[k + 1] = a[k];
//将a[i]放到正确位置上
a[k + 1] = temp;
}
}
}

//插入排序2
//将搜索和数据后移这二个步骤合并。即每次a[i]先和前面一个数据a[i-1]比较,
//如果a[i] > a[i-1]说明a[0…i]也是有序的,无须调整。否则就令j=i-1,temp=a[i]。
//然后一边将数据a[j]向后移动一边向前搜索,当有数据a[j]<a[i]时停止并将temp放到a[j + 1]处。
void Insertsort2(int a[], int n)
{
int i, j;
for (i = 1; i < n; i++)
if (a[i] < a[i - 1])
{
int temp = a[i];
for (j = i - 1; j >= 0 && a[j] > temp; j--)
a[j + 1] = a[j];
a[j + 1] = temp;
}
}

//插入排序3:直接插入排序
//对将a[j]插入到前面a[0…j-1]的有序区间所用的方法进行改写,用数据交换代替数据后移。
//如果a[j]前一个数据a[j-1] > a[j],就交换a[j]和a[j-1],再j--直到a[j-1] <= a[j]。
//这样也可以实现将一个新数据新并入到有序区间。
void Insertsort3(int a[], int n)
{
int i, j;
for (i = 1; i < n; i++)
for (j = i - 1; j >= 0 && a[j] > a[j + 1]; j--)
Swap(a[j], a[j + 1]);
}

//排序算法之三:希尔排序
//基本思想:先将整个待排元素序列分割成若干子序列(由相隔某个
//“增量 ”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,
//待整个序列中的元素基本有序(增量足够小)时,再对全体进行一次直接插
//入排序。因为直接插在元素基本有序的情况下(接近最好情况),效率是
//很高的,因此希尔排序在时间效率上比前两种方法有较大提。

//希尔排序1:定义
void shellsort1(int a[], int n)
{
int i, j, gap;
for (gap = n / 2; gap > 0; gap /= 2) //步长
{
for (i = 0; i < gap; i++) //按组排序
{
for (j = i + gap; j < n; j += gap)
{
if (a[j] < a[j - gap])
{
int temp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > temp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = temp;
}
}
}
}

}
//希尔排序2
//进行下改进和优化:
//以第二次排序为例,原来是每次从1A到1E,从2A到2E,可以改成从1B开始,先和1A比较,
//然后取2B与2A比较,再取1C与前面自己组内的数据比较…….。
//这种每次从数组第gap个元素开始,每个元素与自己组内的数据进行直接插入排序显然也是正确的。
void shellsort2(int a[], int n)
{
int j, gap;
for (gap = n / 2; gap > 0; gap /= 2)
for (j = gap; j < n; j++) //从数组第gap个元素开始
if (a[j] < a[j - gap]) //每个元素与自己组内的数据进行直接插入排序
{
int temp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > temp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = temp;
}
}

//希尔排序3:
//直接排序3应用于希尔排序
void shellsort3(int a[], int n)
{
int i, j, gap;
for (gap = n / 2; gap > 0; gap /= 2)
for (i = gap; i < n; i++)
for (j = i - gap; j >= 0 && a[j] > a[j + gap]; j -= gap)
Swap(a[j], a[j + gap]);
}

//选择排序
//选择排序和插入排序类似,都将数据分为有序区和无序区。
//不同的是插入排序是将无区的第一个元素插入到有序区以形成一个更大的入到有序区,
//而选择排序是从无序区选择一个最小的元素放到有序区的最后。

//设数组为a[0…n - 1]。
//1. 初始时,数组全为无序区为a[0..n - 1]。令i = 0
//2. 在无序区a[i…n - 1]中选取一个最小的元素,将其与a[i]交换。交换之后a[0…i]就形成了一个有序区。
//3. i++并重复第二步直到i == n - 1。
//排序完成。

// 直接选择排序
void Selectsort(int a[], int n)
{
int i, j, nMinIndex;
for (i = 0; i < n; i++)
{
nMinIndex = i; //找最小元素的位置
for (j = i + 1; j < n; j++)
if (a[j] < a[nMinIndex])
nMinIndex = j;
Swap(a[i], a[nMinIndex]); //将这个元素放到无序区的开头
}
}

//归并排序
//基本思路就是将组分成两组 A,B,如果这两组内的数据都是有序,那么就可以很方便将两组数据进行排序。
//如何让这二组内数据有了?可以将 A,B组各自再分成两组。依次类推, 当出来的小只有一个数据时可以认为
//这个小组内已经达到了有序,然后再合并相邻的二就。这样通过先递归的分解数列,再合并数列就完成了归并排序。

//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
int i = first, j = mid + 1;
int m = mid, n = last;
int k = 0;
while (i <= m && j <= n)
{
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= m)
temp[k++] = a[i++];
while (j <= n)
temp[k++] = a[j++];
for (i = 0; i < k; i++)
a[first + i] = temp[i];
}

void mergesort(int a[], int first, int last, int temp[])
{
if (first < last)
{
int mid = (first + last) / 2;
mergesort(a, first, mid, temp); //左边有序
mergesort(a, mid + 1, last, temp); //右边有序
mergearray(a, first, mid, last, temp); //再将二个有序数列合并
}
}

bool MergeSort(int a[], int n)
{
int *pTempArray = new int
;
if (pTempArray == NULL)
return false;
mergesort(a, 0, n - 1, pTempArray);
delete[] pTempArray;
return true;
}

//快速排序

//快速排序1:定义
//对挖坑填数进行总结
//1.i = L; j R; i = L; j R; i = L; j R; i = L; j R; i = L; j R; i = L; j R; 将基准数挖出 将基准数挖出 形成第一个坑 a[i]a[i]a[i] 。
//2.j-- 由后向前找比它小的数,到 后挖出此数填前一个坑 a[i]a[i]a[i] 中。
//3.i++ 由前向后找比它大的数,到也挖出此填一个坑 由前向后找比它大的数,到也挖出此填一个坑 a[j] 中。
//4.再重复执行 2,3二步,直到 i == j i == j,将基准数填入 a[i]a[i]a[i] 中

int AdjustArray(int s[], int l, int r) //返回调整后基准数的位置
{
int i = l, j = r;
int x = s[l]; //s[l]即s[i]就是第一个坑
while (i < j)
{
// 从右向左找小于x的数来填s[i]
while (i < j && s[j] >= x)
j--;
if (i < j)
{
s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑
i++;
}
// 从左向右找大于或等于x的数来填s[j]
while (i < j && s[i] < x)
i++;
if (i < j)
{
s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑
j--;
}
}
//退出时,i等于j。将x填到这个坑中。
s[i] = x;
return i;
}
void quick_sort1(int s[], int l, int r)
{
if (l < r)
{
int i = AdjustArray(s, l, r);//先成挖坑填数法调整s[]
quick_sort1(s, l, i - 1); // 递归调用
quick_sort1(s, i + 1, r);
}
}

//快速排序2
void quick_sort2(int s[], int l, int r)
{
if (l < r)
{
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int i = l, j = r, x = s[l];
while (i < j)
{
while (i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if (i < j)
s[i++] = s[j];
while (i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if (i < j)
s[j--] = s[i];
}
s[i] = x;
quick_sort2(s, l, i - 1); // 递归调用
quick_sort2(s, i + 1, r);
}
}


测试代码:

#include <iostream>
#include <time.h>
#include <math.h>
#include <windows.h>
using namespace std;

int main(
b3b2
)
{
srand((int)time(0));

int N = 100000;
int *A = new int
;
for (int i = 0; i < N; i++)
{
A[i] = (rand() % 100);
}
printf("数列生成完毕!!\n");
SYSTEMTIME time_begin, time_end;

//冒泡排序
int *BubbleA = new int
;
memcpy(BubbleA, A, N*sizeof(int));
GetLocalTime(&time_begin);
BubbleSort3(BubbleA, N);
GetLocalTime(&time_end);
printf("冒泡排序耗时:%d毫秒\n"
, time_end.wMilliseconds - time_begin.wMilliseconds
+ 1000 * (time_end.wSecond - time_begin.wSecond + 60 * (time_end.wMinute - time_begin.wMinute)));
delete[] BubbleA;

//插入排序
int *insertA = new int
;
memcpy(insertA, A, N*sizeof(int));
GetLocalTime(&time_begin);
Insertsort3(insertA, N);
GetLocalTime(&time_end);
printf("插入排序耗时:%d毫秒\n"
, time_end.wMilliseconds - time_begin.wMilliseconds
+ 1000 * (time_end.wSecond - time_begin.wSecond + 60 * (time_end.wMinute - time_begin.wMinute)));
delete[] insertA;

//选择排序
int *selectA = new int
;
memcpy(selectA, A, N*sizeof(int));
GetLocalTime(&time_begin);
Selectsort(selectA, N);
GetLocalTime(&time_end);
printf("选择排序耗时:%d毫秒\n"
, time_end.wMilliseconds - time_begin.wMilliseconds
+ 1000 * (time_end.wSecond - time_begin.wSecond + 60 * (time_end.wMinute - time_begin.wMinute)));
delete[] selectA;

//希尔排序
int *shellA = new int
;
memcpy(shellA, A, N*sizeof(int));
GetLocalTime(&time_begin);
shellsort3(shellA, N);
GetLocalTime(&time_end);
printf("希尔排序耗时:%d毫秒\n"
, time_end.wMilliseconds - time_begin.wMilliseconds
+ 1000 * (time_end.wSecond - time_begin.wSecond + 60 * (time_end.wMinute - time_begin.wMinute)));
delete[] shellA;

//归并排序
int *mergeA = new int
;
memcpy(mergeA, A, N*sizeof(int));
GetLocalTime(&time_begin);
MergeSort(mergeA, N);
GetLocalTime(&time_end);
printf("归并排序耗时:%d毫秒\n"
, time_end.wMilliseconds - time_begin.wMilliseconds
+ 1000 * (time_end.wSecond - time_begin.wSecond + 60 * (time_end.wMinute - time_begin.wMinute)));
delete[] mergeA;

//快速排序
int *quickA = new int
;
memcpy(quickA, A, N*sizeof(int));
GetLocalTime(&time_begin);
MergeSort(quickA, N);
GetLocalTime(&time_end);
printf("快速排序耗时:%d毫秒\n"
, time_end.wMilliseconds - time_begin.wMilliseconds
+ 1000 * (time_end.wSecond - time_begin.wSecond + 60 * (time_end.wMinute - time_begin.wMinute)));
delete[] quickA;

delete[] A;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  排序算法