一、插入排序
1、直接插入排序
从第一个元素开始,依次取出,比较取出的元素和其左边的所有元素,如果比左边所有元素大,则直接插入,否则依次将比该元素大的元素向后移动,然后插入即可。
例:原始数据:46 25 31 18 84 18 20 60
【46】 25 31 18 84 18 20 60
【25 46】 31 18 84 18 20 60
【25 31 46】 18 84 18 20 60
【18 25 31 46】 84 18 20 60
【18 25 31 46 84】 18 20 60
【18 18 25 31 46 84】 20 60
【18 18 20 25 31 46 84】 60
【18 18 20 25 31 46 60 84】
#include<stdio.h>
void InsertSort(int k[],int n) //n为元素个数
{
int temp;//temp暂时存储取出的值
for( int i = 0 ; i < n ; i++ )
{
if( k[i-1] > k[i] )
{
temp = k[i];
//将比第i个元素大的左边所有元素向后移,给此元素找位置
for( int j = i-1 ; k[j] > temp ; j-- )
{
k[j+1] = k[j];
}
//找到元素位置,插入
k[j+1] = temp;
}
}
}
int main()
{
int a[8]={46, 25, 31, 18, 84, 18, 20, 60};
InsertSort(a,8);
printf("排序后的结果是:");
for( int i = 0 ; i < 8 ; i++ )
{
printf("%d\t",a[i]);
}
return 0;
}
时间复杂度: 最好复杂度:O(n);最坏复杂度:O(n2)
平均复杂度:O(n2) 稳定
2、希尔排序
用元素个数除以2或3求得间距d1,从第一个元素开始,每隔d1个间距的元素分为一组,将每组的元素排序,再将d1除以2或3求得间距d2,同上,直到间距变为1。
例:原始数据:46 25 31 18 84 18 20 60
d1=4排完序后 -------- 46 18 20 18 84 25 31 60
d2=2排完序后 -------- 20 18 31 18 46 25 84 60
d3=1排完序后 -------- 18 18 20 25 31 46 60 84
#include <stdio.h>
void InsertSort(int k[], int n)
{
int i, j, temp;
int d = n;
do
{
d = d/2;
for( i=d; i < n; i++ )
{
if( k[i-d] > k[i] )
{
temp = k[i];
for( j=i-d; k[j] > temp; j-=d )
{
k[j+d] = k[j];
}
k[j+d] = temp;
}
}
}while(d > 1);
}
int main()
{
int i, a[8] = {46,25,31,18,84,18,20,60};
InsertSort(a, 8);
printf("排序后的结果是:");
for( i=0; i < 8; i++ )
{
printf("%d\t", a[i]);
}
return 0;
}
时间复杂度: 平均复杂度:O(n1.3) 不稳定
3、折半插入排序(二分查找)
key为要查找的元素,先将low指向第一个元素,high指向最后一个元素,在low<high的条件下,mid指向中间的元素,如果midVal<key,low=mid+1;如果midVal>key,high=mid-1;如果midVal=key,则查找成功。low>high则查找失败。
注意:在有序的一组数中查找。
#include<stdio.h>
int binarySearch(int a[],int n,int key)
{
int low=1,high=n;
while(low<=high){
int mid=(low+high)/2;
int midVal=a[mid];
if(midVal<key){
low=mid+1;
}
else if(midVal>key){
high=mid-1;
}
else
return mid;
}
return -1;
}
int main(){
int i,val,ret;
int a[8]={1,2,3,4,5,6,7,8};
for(i=0;i<8;i++){
printf("%d\t",a[i]);
}
printf("\n请输入要查找的元素:");
scanf("%d",&val);
ret=binarySearch(a,8,val);
if(-1==ret){//ret为返回值,必须在等号右边
printf("查找失败\n");
}
else{
printf("查找成功%d\n",val);
}
return 0;
}
时间复杂度: O(n2)
4、简单选择排序(直接选择排序)
首先从1到n这n个记录中找出最小关键字所在的记录,然后把它与第1个记录交换位置,接着再从2到n这n-1个记录中,找出最小(也就是整个文件中次小的)关键字所在的记录和第2个记录交换位置,依次进行,直到从n-1到n,最后两个记录中,找出最小关键字所在记录把它和n-1位置上的记录交换位置为止,排序结束。
例:原始数据:46 25 31 18 84 18 20 60
【18】 25 31 46 84 18 20 60
【18 18】 31 46 84 25 20 60
【18 18 20】 46 84 25 31 60
【18 18 20 25】 84 46 31 60
【18 18 20 25 31】 46 84 60
【18 18 20 25 31 46】 84 60
【18 18 20 25 31 46 60】 84
【18 18 20 25 31 46 60 84】
#include <stdio.h>
void SelectSort(int k[], int n)
{
int i, j, min, temp, count1=0, count2=0;
for( i=0; i < n-1; i++ )
{
min = i;
for( j=i+1; j < n; j++ )
{
count1++;
if( k[j] < k[min] )
{
min = j;
}
}
if( min != i )
{
count2++;
temp = k[min];
k[min] = k[i];
k[i] = temp;
}
}
printf("总共进行了%d次比较,进行了%d次移动!", count1, count2);
}
int main()
{
int i, a[8] = {46,25,31,18,84,18,20,60};
SelectSort(a, 8);
printf("排序后的结果是:");
for( i=0; i < 8; i++ )
{
printf("%d\t", a[i]);
}
return 0;
}
时间复杂度: O(n2) 不稳定
5、堆排序
a.将无序序列构建成一个堆(完全二叉树),根据升序降序需求选择大顶堆或小顶堆;
b.将堆顶元素与末尾元素互换,将最大(小)元素沉到数组末端;
c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
#include <stdio.h>
int count = 0;
void swap(int k[], int i, int j)
{
int temp = k[i];
k[i] = k[j];
k[j] = temp;
}
void HeapAdjust(int k[], int s, int n)
{
int temp = k[s];
for( int 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)
{
for(int i=n/2; i > 0; i-- )
{
HeapAdjust(k, i, n);
}
for(int i=n; i > 1; i-- )
{
swap(k, 1, i);
HeapAdjust(k, 1, i-1);
}
}
int main()
{
int a[8] = {46,25,31,18,84,18,20,60};
HeapSort(a, 7);
printf("总共执行 %d 次比较!", count);
printf("排序后的结果是:");
for( int i=1; i < 8; i++ )
{
printf("%d\t", a[i]);
}
return 0;
}
时间复杂度: O(nlog2n) 不稳定
二、交换排序
6、冒泡排序
#include<stdio.h>
void BubbleSort(int k[], int n)
{
int temp;
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-1-i;j++)
{
if(k[j]>k[j+1])
{
temp=k[j];
k[j]=k[j+1];
k[j+1]=temp;
}
}
}
}
int main()
{
int i, a[8] = {46,25,31,18,84,18,20,60};
BubbleSort(a, 8);
printf("排序后的结果是:");
for( i=0; i < 8; i++ )
{
printf("%d\t", a[i]);
}
return 0;
}
时间复杂度: 最好复杂度:O(n) ; 最坏复杂度:O(n2); 平均复杂度:O(n2) 稳定
7、快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快排第i趟至少应有i个元素就位。(元素的左边元素都小于该元素,元素的右边元素都小于该元素。)
a.设置两个变量i、j,排序开始的时候:i=0,j=N-1;
b.以第一个数组元素作为关键数据,赋值给key,即key=A[0];
c.从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;
d.从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;
e.重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
例:原始数据:46 25 31 18 84 18 20 60
一次-------------【20 25 31 18 18】 46 【84 60】
二次-------------【18 18】 20 【31 25】 46 【60】 84
三次------------- 18 【18】 20 【25】 31 46 60 84
排序结果------- 18 18 20 25 31 46 60 84
#include <stdio.h>
void swap(int k[], int low, int high)
{
int 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()
{
int i, a[8] = {46,25,31,18,84,18,20,60};
QuickSort(a, 8);
printf("排序后的结果是:");
for( i=0; i < 8; i++ )
{
printf("%d\t", a[i]);
}
return 0;
}
时间复杂度: O(nlog2n) 不稳定
二、归并排序
8、归并排序
将两个顺序序列合并成一个顺序序列。(两两归并)
例:原始数据:46 25 31 18 84 18 20 60
八个文件----[46] [25] [31] [18] [84] [18] [20] [60]
一次归并----[25 46] [18 31] [18 84] [20 60]
二次归并----[18 25 31 46] [18 20 60 84]
三次归并----[18 18 20 25 31 46 60 84]
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 8
void MergeSort(int k[], int n)
{
int i, next, left_min, left_max, right_min, right_max;
int *temp = (int *)malloc(n * sizeof(int));
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];
}
while( next > 0 )
{
k[--right_min] = temp[--next];
}
}
}
}
int main()
{
int i, a[8] = {46,25,31,18,84,18,20,60};
MergeSort(a, 8);
printf("排序后的结果是:");
for( i=0; i < 8; i++ )
{
printf("%d\t", a[i]);
}
return 0;
}
时间复杂度: O(nlog2n) 稳定