排序:使一个无序序列转变为有序序列的过程
排序的稳定性:
假设ki = kj, (1<= i <= n, 1<= j <= n, i != j),且在排序前的序列中ri领先于rj(即i<j)
如果排序后ri仍领先于rj,则称所用的排序方法是稳定的,否则是不稳定的
影响排序算法性能的几个要素:
时间性能,辅助空间、算法的复杂性
冒泡排序:每次取相邻两个数做比较,并在符合交换条件时交换,直到整个数组均符合条件
#include <stdio.h>
#include <stdlib.h>
void Print(int *k, int n)
{
int i;
printf("此时的数组顺序为:\n");
for(i=0; i<n-1; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
//不正宗的冒泡排序算法
void BubbleSort(int *k, int n)
{
int i, j, temp, count1 = 0, count2 = 0;
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
count1++;
if(k[i] > k[j])
{
temp = k[j];
k[j] = k[i];
k[i] = temp;
count2++;
}
}
}
Print(k, n);
printf("此次共进行了%d次比较,%d次移动~\n", count1, count2);
}
//正宗的冒泡排序算法(从下往上冒)
void TrueBubbleSort(int *k, int n)
{
int i, j, temp, count1 = 0, count2 = 0;
for(i=0; i<n-1; i++)
{
for(j=n-1; j>i; j--)
{
count1++;
if(k[j-1] > k[j])
{
temp = k[j];
k[j] = k[j-1];
k[j-1] = temp;
count2++;
}
}
}
Print(k, n);
printf("此次共进行了%d次比较,%d次移动~\n", count1, count2);
}
//正宗的冒泡排序算法优化
void BetterTrueBubbleSort(int *k, int n)
{
int i, j, temp, count1 = 0, count2 = 0, flag = 1;
for(i=0; i<n-1 && flag; i++)
{
flag = 0;
for(j=n-1; j>i; j--)
{
count1++;
if(k[j-1] > k[j])
{
temp = k[j];
k[j] = k[j-1];
k[j-1] = temp;
count2++;
flag = 1;
}
}
}
Print(k, n);
printf("此次共进行了%d次比较,%d次移动~\n", count1, count2);
}
int main()
{
int a[10] = {9,8,7,6,5,4,2,1,0,3};
//int b[10] = {9,8,7,6,5,4,2,1,0,3};
//int c[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n不正宗的冒泡排序:\n\n");
BubbleSort(a, n);
printf("\n正宗的冒泡排序:\n\n");
TrueBubbleSort(a, n);
printf("\n正宗的冒泡排序优化:\n\n");
BetterTrueBubbleSort(a, n);
return 0;
}
选择排序(一般比冒泡排序效率高):在数组中每次选取最大或最小的数移到最前面(迭代范围依次减1),直到数组有序
#include <stdio.h>
void Print(int *k, int n)
{
int i;
printf("此时的数组顺序为:\n");
for(i=0; i<n-1; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
void SelectSort(int *k, int n)
{
int i, j, min, temp;
int count1 = 0, count2 = 0;
for(i=0; i<n-1; i++)
{
min = i;
count1++;
for(j=i+1; j<n; j++)
{
if(k[j] < k[min])
{
min = j;
}
}
if(min != i)
{
count2++;
temp = k[min];
k[min] = k[i];
k[i] = temp;
}
}
printf("此次共进行了%d次比较,%d次移动~\n", count1, count2);
}
int main(void)
{
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n选择排序:\n\n");
SelectSort(a, n);
return 0;
}
直接插入排序:每次将数组前面M个元素看作有序(M从1开始),将后面的元素与有序序列作比较并插入到相应的位置,重复前两步直至数组有序
#include <stdio.h>
#include <stdlib.h>
void Print(int *k, int n)
{
int i;
printf("此时的数组顺序为:\n");
for(i=0; i<n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
void InsertSort(int *k, int n)
{
int i, j, temp;
for(i=1; i<n; i++)
{
if( k[i] < k[i-1] )
{
temp = k[i];
for(j=i-1; k[j]>temp; j--)
{
k[j+1] = k[j];
}
k[j+1] = temp;
}
}
Print(k, n);
}
int main(void)
{
//int a[10] = {5,2,6,0,3,9,1,7,4,8};
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n直接插入排序:\n\n");
InsertSort(a, n);
return 0;
}
希尔排序:时间复杂度(n*logn)每次排序取一定的间隔对子数组进行比较,期间间隔不断缩小直至为1
#include <stdio.h>
#include <stdlib.h>
void Print(int *k, int n)
{
int i;
printf("此时的数组顺序为:\n");
for(i=0; i<n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
void InsertSort(int *k, int n)
{
int i, j, temp;
int gap = n;
do
{
gap = gap/3 + 1;
for(i=gap; i<n; i+=gap)
{
if( k[i] < k[i-gap] )
{
temp = k[i];
for(j=i-gap; k[j]>temp && j>=0; j-=gap)
{
k[j+gap] = k[j];
}
k[j+gap] = temp;
}
}
}while(gap > 1);
Print(k, n);
}
int main(void)
{
//int a[10] = {5,2,6,0,3,9,1,7,4,8};
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n希尔排序:\n\n");
InsertSort(a, n);
return 0;
}
堆排序:利用堆进行排序,将待排序的序列构造成堆(大顶堆或小顶堆),求最大值时取堆顶元素与末尾元素交换,再将剩余的元素重新构造成堆,重复上述操作,直至排序完成
#include <stdio.h>
#include <stdlib.h>
int count = 0;
void Print(int *k, int n)
{
int i;
printf("\n当前数组的顺序为:\n");
for(i=1; i<=n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
void swap(int *k, int i, int j)
{
int temp;
temp = k[i];
k[i] = k[j];
k[j] = temp;
}
void HeapAdjust(int *k, int s, int n)
{
int i, temp;
temp = k[s];
for(i=2*s; i<=n; i*=2)
{
count++;
if(i < n && k[i] < k[i+1])
{
i++;
}
if(temp >= k[i])
{
break;
}
k[s] = k[i];
s = i;
}
k[s] = temp;
}
void HeapSort(int *k, int n)
{
int i;
for(i=n/2; i>0; i--)
{
HeapAdjust(k, i, n);
}
for(i=n; i>1; i--)
{
swap(k, 1, i);
HeapAdjust(k, 1, i-1);
}
Print(k, n);
}
int main(void)
{
int a[10] = {-1,8,7,6,5,4,2,1,0,3};
int n = 9;
Print(a, n);
printf("\n堆排序:\n\n");
HeapSort(a, n);
printf("总共进行%d次比较~\n", count);
return 0;
}
归并排序:
2路归并排序:将有n个记录的序列看成是拥有n个有序的子序列,每个子序列长度为1,然后两两归并,得到n/2个长度为2的有序子序列,在两两归并,依此类推,直到得到长度为n的有序序列
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
//打印数组
void Print(int *k, int n)
{
int i;
printf("\n当前数组的顺序为:\n");
for(i=0; i<n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
//归并排序归并部分
void Merging(int *list1, int list1_size, int *list2, int list2_size)
{
int i, j, k, m;
int temp[MAXSIZE];
i = j = k = 0;
while(i<list1_size && j<list2_size)
{
if(list1[i] < list2[j])
{
temp[k++] = list1[i++];
}
else
{
temp[k++] = list2[j++];
}
}
while(i < list1_size)
{
temp[k++] = list1[i++];
}
while(j < list2_size)
{
temp[k++] = list2[j++];
}
for(m=0; m<(list1_size + list2_size); m++)
{
list1[m] = temp[m];
}
}
//归并排序递归部分
void MergeSort(int *k, int n)
{
//将序列分为两部分,并且每部分与元素个数至少为2
if(n > 1)
{
int *list1 = k;
int list1_size = n/2;
int *list2 = k + n/2;
int list2_size = n - list1_size;
MergeSort(list1, list1_size);
MergeSort(list2, list2_size);
Merging(list1, list1_size, list2, list2_size);
}
}
int main(void)
{
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n堆排序:\n\n");
MergeSort(a, n);
Print(a, n);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
//打印数组
void Print(int *k, int n)
{
int i;
printf("\n当前数组的顺序为:\n");
for(i=0; i<n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
//归并排序迭代部分
void MergeSort(int *k, int n)
{
int i, left_min, left_max, right_min, right_max, next;
//分配一个动态内存用于存储排序后的序列
int *temp = (int *)malloc(n * sizeof(int));
if(!temp)
{
printf("分配动态内存失败!\n");
exit(1);
}
//根据步长i对序列作比较
for(i=1; i<n; i*=2)
{
//根据步长分配每个小区间的空间长度
for( left_min = 0; left_min < n-i; left_min = right_max)
{
right_min = left_max = left_min + i;
right_max = left_max + i;
if(right_max > n)
{
right_max = n;
}
next = 0;
while(left_min < left_max && right_min < right_max)
{
if(k[left_min] < k[right_min])
{
temp[next++] = k[left_min++];
}
else
{
temp[next++] = k[right_min++];
}
}
//当左区间存在较大值时,将剩下的值放到右区间最右处
while(left_min < left_max)
{
k[--right_min] = k[--left_max];
}
//将暂存在temp空间中的已排序序列放回原数组中
while(next > 0)
{
k[--right_min] = temp[--next];
}
}
}
}
int main(void)
{
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n堆排序:\n\n");
MergeSort(a, n);
Print(a, n);
return 0;
}
快速排序:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
//打印数组
void Print(int *k, int n)
{
int i;
printf("\n当前数组的顺序为:\n");
for(i=0; i<n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
void swap(int *k, int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int *k, int low, int high)
{
int point;
point = k[low];
while(low < high)
{
while(low < high && k[high] >= point)
{
high--;
}
swap(k, low, high);
while(low < high && k[low] <= point)
{
low++;
}
swap(k, low, high);
}
return low;
}
void QSort(int *k, int low, int high)
{
int point;
if(low < high)
{
point = Partition(k, low, high);
QSort(k, low, point-1);
QSort(k, point+1, high);
}
}
//快速排序
void QuickSort(int *k, int n)
{
QSort(k, 0, n-1);
}
int main(void)
{
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n快速排序:\n\n");
QuickSort(a, n);
Print(a, n);
return 0;
}
快速排序算法优化:
1.优化选取基准点:三数取中法,从序列中任意取三个数取中间的值作为基准点
2.优化掉不必要的交换:
3.优化小数组时的排序方案:待插入数组规模小,直接插入;大规模,快速排序(有递归)
4.优化递归操作:
优化示例:
/*快速排序算法的优化(三数取中法)*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
//打印数组
void Print(int *k, int n)
{
int i;
printf("\n当前数组的顺序为:\n");
for(i=0; i<n; i++)
{
printf("%d ", k[i]);
}
printf("\n");
}
void swap(int *k, int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int *k, int low, int high)
{
int point;
int m = low + (high - low)/2;
if(k[low] > k[high])
{
swap(k, low, high);
}
if(k[m] > k[high])
{
swap(k, m, high);
}
if(k[m] > k[low])
{
swap(k, m, low);
}
point = k[low];
while(low < high)
{
while(low < high && k[high] >= point)
{
high--;
}
swap(k, low, high);
while(low < high && k[low] <= point)
{
low++;
}
swap(k, low, high);
}
return low;
}
void QSort(int *k, int low, int high)
{
int point;
if(low < high)
{
point = Partition(k, low, high);
QSort(k, low, point-1);
//QSort(k, point+1, high);
}
}
//快速排序
void QuickSort(int *k, int n)
{
QSort(k, 0, n-1);
}
int main(void)
{
int a[10] = {9,8,7,6,5,4,2,1,0,3};
int n = 10;
Print(a, n);
printf("\n快速排序:\n\n");
QuickSort(a, n);
Print(a, n);
return 0;
}
排序算法:
1.插入排序类:直接插入排序,希尔排序
2.选择排序类:选择排序、堆排序
3.交换排序类:冒泡排序,快速排序
4.归并排序类:归并排序
各排序算法特点: