- 插入排序
- 最坏的时间复杂度是O(n²),最好是O(n),并且是稳定的
1、思想:插入排序通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入 ,如此重复,直至完成序列排序。
2、 算法分析
1. 从序列第一个元素开始,该元素可以认为已经被排序
2. 取出下一个元素,设为待插入元素,在已经排序的元素序列中从后向前扫描,如果该元素(已排序)大于待插入元素,将该元素移到下一位置。
3. 重复步骤2,直到找到已排序的元素小于或者等于待排序元素的位置,插入元素
4. 重复2,3步骤,完成排序。
红色框起来的部分是已排序序列
#include<stdio.h>
#include<stdlib.h>
void InsertSort(int arr[], int len)
{
int tmp = 0;
int i = 1;
int j = i - 1;
for (i; i < len; ++i)
{
tmp = arr[i];
for (j = i - 1; j >= 0 && arr[j] > tmp; --j)
{
arr[j + 1] = arr[j];//将大元素后移
}
arr[j + 1] = tmp;
}
}
int main()
{
int arr[] = { 32, 1244, 32, 43, 45, 34, 6, 547, 65, 8679, 678, 8, 66 };
int len = sizeof(arr) / sizeof(arr[0]);
InsertSort(arr,len);
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
- 简单选择排序
- 最好和最差的平均复杂度都是O(n²),并且是不稳定的
- 思想:每一趟从带排序的数据元素中选出最小(最大)元素,与待排序数列的第一个元素进行交换
红色框起来的是待排序数列的最小元素,绿色框起来的是待排序数列的第一个元素
#include<stdio.h>
#include<stdlib.h>
void SimpleSelectSort(int arr[],int len)
{
int i=0;
int j=i+1;
int min=i;
for(i;i<len-1;i++)
{
for(j=i+1;j<len;j++)
{
if(arr[j]<arr[min])
min=j;
}
if(min!=i)
{
int tmp=arr[min];
arr[min]=arr[i];
arr[i]=tmp;
}
}
}
int main()
{
int arr[]={9,2,8,3,7,4,6,5,1};
int len = sizeof(arr) / sizeof(arr[0]);
SimpleSelectSort(arr,len);
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
- 希尔排序
- 最坏的时间复杂度是O(n²),最好是O(n),并且是不稳定的
希尔排序又称“缩小增量排序”,也是一种插入排序类的方法,在时间效率上有较大的改进。
- 思想:先将整个待排序序列分割成若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,在对全体记录进行一次直接插入排序
#include<stdio.h>
#include<stdlib.h>
void Shell(int arr[],int len,int k)
{
int tmp=0;
int i=k;
int j=i-k;
for(int i;i<len;i++)
{
tmp=arr[i];
for(j=i-k;j>=0&&arr[j]>tmp;j-=k)
{
arr[j+k]=arr[j];
}
arr[j+k]=tmp;
}
}
void ShellSort(int arr[],int len,int k[],int klen)
{
for(int i=0;i<klen;i++)
{
Shell(arr,len,k[i]);
}
}
int main()
{
int arr[]={49,38,65,97,76,13,27,49,55,04};
int len=sizeof(arr)/sizeof(arr[0]);
int k[]={5,3,1};
int klen=sizeof(k)/sizeof(k[0]);
ShellSort(arr,len,k,klen);
for (int i = 0; i < len; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
- 堆排序
-
最好和最坏和平均时间复杂度都是O(nlogn),并且是不稳定的
1.思想:堆实质上是一种完全二叉树,分为打定队和小顶堆,大顶堆就是根节点始终大于等于子节点,两个子节点之间大小随意,小顶堆反之。
堆排序首先就是要把一个无序序列排成一个大顶堆(升序)然后用排好的大顶堆的根节点和最后一个子节点交换,就得到最大值(最后一个子节点),剔除这个值,之后重复之前的动作(将交换后的二叉树重新排成大顶堆),再进行交换,重复直至剩下一个数。
给定一个无序序列:2,7,6,9,3
#include<stdio.h>
#include<stdlib.h>
void Heap(int arr[],int pos,int len)
{
int i=pos;
int j=i*2+1;
int tmp=0;
for(j;j<len;j=i*2+1)
{
if(j<len-1&&arr[j+1]>arr[j])
++j;
if(arr[i]>=arr[j])
break;
tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
i=j;
}
}
void Sort(int arr[],int len)
{
int tmp;
for(int i=len/2-1;i>=0;i--)
{
Heap(arr,i,len);
}
for(int i=len-1;i>0;i--)
{
tmp=arr[0];
arr[0]=arr[i];
arr[i]=tmp;
Heap(arr,0,i);
}
}
void Show(int arr[], int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[]={31, 231, 23, 21, 3, 21, 4, 2, 41, 23, 1, 232};
int len=sizeof(arr)/sizeof(arr[0]);
Sort(arr,len);
Show(arr, len);
return 0;
}
- 归并排序
-
最好和最坏和平均时间复杂度都是O(n*logn),并且是稳定的
- 思想:将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
创建一个空的数组,将将要合并的两个序列从小到大依次取出合并到新的数组中。
#include<stdio.h>
#include<stdlib.h>
void Gui(int arr[],int a[],int mid,int front,int back)
{
int i=front;
int k=front;
int j=mid+1;
while(i<mid+1&&j<back+1)
{
if(arr[i]<=arr[j])
a[k++]=arr[i++];
if(arr[i]>arr[j])
a[k++]=arr[j++];
}
while(i<mid+1)
{
a[k++]=arr[i++];
}
while(j<back+1)
{
a[k++]=arr[j++];
}
for(int i=front;i<=back;i++)
{
arr[i]=a[i];
}
}
void GuiBing(int arr[],int a[],int front,int back)
{
int mid=(front+back)/2;
if(front<back)
{
//int mid=(front+back)/2;
GuiBing(arr,a,front,mid);
GuiBing(arr,a,mid+1,back);
Gui(arr,a,mid,front,back);
}
}
void Sort(int arr[], int len)
{
int *a = (int*)malloc(sizeof(arr[0])*len);
GuiBing(arr, a, 0, len - 1);
free(a);
}
void Show(int arr[],int len)
{
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[]={5,7,3,6,9,2,4,1};
int len=sizeof(arr)/sizeof(arr[0]);
Sort(arr,len);
Show(arr,len);
return 0;
}
- 基数排序
-
最好和最坏和平均时间复杂度都是O(n*k),并且是稳定的
- 思想:基数排序又称为“桶子法”,从低位开始将待排序的数按照这一位的值放到相应的编号为0~9的桶中。等到低位排完得到一个子序列,再将这个序列按照次低位的大小进入相应的桶中,一直排到最高位为止,数组排序完成。LSD——从低位向高位排,MSD——从高位向低位排。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXSIZE 10
int FindMax(int arr[],int len)
{
int max=arr[0];
for(int i=0;i<len;i++)
{
if(max<arr[i])
{
max=arr[i];
}
}
int count=0;
while(max!=0)
{
max/=10;
count++;
}
return count;
}
int FindFin(int num, int fin)
{
return num / (int)pow(10.0, fin) % 10;
}
void Radix(int arr[], int len, int fin)
{
int backet[10][MAXSIZE] = {};
int finnum = 0;
int num[10] = {};
for (int i = 0; i < len; ++i)
{
finnum = FindFin(arr[i], fin);
backet[finnum][num[finnum]] = arr[i];
num[finnum]++;
}
int aindex = 0;
int bindex = 0;
for (int i = 0; i < 10; ++i)
{
bindex = 0;
while (bindex != num[i])
{
arr[aindex++] = backet[i][bindex++];
}
}
}
void RadixSort(int arr[], int len)
{
int max = FindMax(arr, len);
for (int i = 0; i < max; ++i)
{
Radix(arr, len, i);
}
}
void Show(int arr[],int len)
{
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {99,87,107,231,67,45,32,123,8,36 };
int len = sizeof(arr) / sizeof(arr[0]);
RadixSort(arr, len);
Show(arr, len);
return 0;
}
- 快速排序
-
平均实际复杂度为O(nlogn),最差时间复杂度为O(n2),并且是不稳定的
- 思想:
#include<stdio.h>
void quicksort(int arr[],int left,int right)
{
int i=left;
int j=right;
int tmp=arr[left];
int t;
if(left>right)
return;
while(i!=j)
{
while(tmp>=arr[j]&&i<j)
j--;
while(tmp<=arr[i]&&i<j)
i++;
if(i<j)
{
t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
arr[left]=arr[i];
arr[i]=tmp;
quicksort(arr,left,j-1);
quicksort(arr,i+1,right);
}
void Show(int arr[],int len)
{
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[]={7,3,2,4,5,9,8,1,6};
int len=sizeof(arr)/sizeof(arr[0]);
quicksort(arr,0,len);
Show(arr,len);
return 0;
}
- 冒泡排序
- 最好和最差的平均复杂度都是O(n²),并且是稳定的
1.思想:从数组头部开始遍历,不断比较相邻的两个元素的大小,让较大的元素往后移,直到数组末尾,经过第一轮的比较,就将最大的元素移动到最后一个位置。
第一轮结束后继续第二轮,仍然从数组头部开始比较,让较大的元素后移,就可以找到次大的元素,以此类推。
#include<stdio.h>
#include<stdlib.h>
void BubbleSort(int arr[],int len)
{
int tmp=0;
for(int i=0;i<len-1;i++)
{
for(int j=0;j<len-i-1;j++)
{
if(arr[j]>arr[j+1])
{
tmp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
}
int main()
{
int arr[] = { 31, 2, 342, 5, 34, 6, 45, 7, 56, 7 };
int len = sizeof(arr) / sizeof(arr[0]);
BubbleSort(arr, len);
for(int i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
return 0;
}