1. 直接插入排序
顾名思义,实现排序的方式就是插入。下面由从小到大的顺序进行一次排序。
-
确定一个已经有序的序列,这里先选第一个元素为有序(毕竟只有一个元素)
-
从无序的第一个元素开始比较,有两种情况:
- 无序序列的第一个元素大于有序数列的最后一个元素,就说明这个元素在有序序列中是最大的,所以它的位置是正确的,无需任何操作。
- 无序序列的第一个元素小于有序数列的最后一个元素,该元素位置错误,从有序序列开始遍历,直到找到正确的位置。
将已经遍历过的元素向后移一位,将该元素插入。
重复这种操作,直到全部有序
//代码如下
void InsertSort(int *arr,int length)
{
int Temp;//用于记录无序序列的第一个元素
for (int i=1;i<length;i++)
{
if (arr[i-1]<=arr[i])//第一种情况
continue;
else//第二种情况
{
Temp=arr[i];//记录
for (int j=0;j<i;j++)
{
if (Temp<arr[j])//找到正确的位置
{
for (int k=i;k>=j;k--)//该循环用于将数组后移
arr[k]=arr[k-1];
arr[j]=Temp;//将该元素插入
break;//退出循环
}
}
}
}
}
void InsertSort(int *arr,int length)
{
int Temp,j;
for (int i=1;i<length;i++)
{
Temp=arr[i];
if (arr[i-1]>Temp)
{
for (j=i-1;Temp<arr[j]&&j>=0;j--)
arr[j+1]=arr[j];
arr[j+1]=Temp;
}
}
for (int i=0;i<length;i++)
cout<<arr[i]<<" ";
}
2. 折半插入
折半插入排序是对于插入排序的一个改良版本,将寻找适合插入位置的过程改为了运用二分来进行查找,相比直接插入排序要快一点
void Binary_InsertSort(int arr[],int length)
{
for (int i=1;i<length;i++)
{
int left=0,right=i-1,m;
while (left<=right) //折半查找寻找正确位置
{
m=(left+right)/2;
if (arr[m]>arr[i])
right=m-1;
else
left=m+1;
}
int temp=arr[i];
for (int j=i;j>right+1;j--) //后移
arr[j]=arr[j-1];
arr[right+1]=temp; //插入
}
}
3. 二路插入排序
二路插入排序是对折半插入的进一步改进,减少了交换的次数,其实现方法是多开一个同样大小的数组,再将它想象为一个循环的数组(类似于约瑟夫环),再利用两个指针(并不是真的指针,只是指明数的位置)记录在新建的数组中的最大数与最小数,来减少交换次数。
插入排序:二路插入,这一篇博客写的很好
void InsertSort2(int *a,int n)
{
int first=0,last=0;
int *b=new int[n];
b[0]=a[0];
for (int i=1;i<n;i++)
{
if (a[i]<=b[first])
{
first = (first-1+n)%n;
b[first]=a[i];
}
else if (a[i]>=b[last])
{
last++;
b[last]=a[i];
}
else
{
int left=first, right=last,m,tem;
while (left!=right) //折半查找寻找正确位置
{
tem=(right-left+n)%n;
m=(left+tem/2)%n;
if (a[i] < b[m])
right=m;
else
left=(m+1)%n;
}
for (int j=last+1;j!=left;j=(j-1+n)%n)
b[j]=b[(j-1+n)%n];
b[left] = a[i];
last++;
}
}
for (int i=0;i<n;i++)
a[i]=b[(i+first)%n];
delete []b;
}
4. 希尔排序
void ShellSort(int *arr,int length)
{
for(int gap=length/2;gap>0;gap/=2)
{
for(int i=gap;i<length;++i)
{
int j=i;
while(j-gap>=0 && arr[j-gap]>arr[j])
{
swap(arr[j],arr[j-gap]);
j=j-gap;
}
}
}
}
5. 冒泡排序
void BubbleSort(int *arr,int length)
{
for (int i=length-1;i>0;i--)
{
for (int j=0;j<i;j++)
{
if (arr[j]>arr[j+1])
swap(arr[j+1],arr[j]);
}
}
}
6. 改进冒泡排序
void newBubbleSort(int *arr,int length)
{
int flag=length,k;
for (int i=0;i<flag;i++)
{
k=flag;
flag=0;
for (int j=0;j<k;j++)
{
if (arr[j]<arr[j+1])
{
flag=j;
swap(arr[j],arr[j+1]);
}
}
}
}
7. 鸡尾酒排序
void Cocktail_Sort(int *arr,int length)
{
int low=0;
int high=length;
int flag=1,bound=1;
while (flag)
{
flag=0;
for (int i=low;i<length;i++)
{
if (arr[i]>arr[i+1])
{
swap(arr[i],arr[i+1]);
flag=1;
bound=i;
}
}
high=bound;
for (int i=high;i>low;i--)
{
if (arr[i]<arr[i-1])
{
swap(arr[i],arr[i-1]);
flag=1;
bound=i;
}
}
low=bound;
}
}
8. 快速排序
void Quick_Sort(int *arr,int beginn,int endn)
{
if (beginn<endn)
{
int left=beginn;
int right=endn;
int mid=arr[beginn];
while (left<right)
{
while (left<right&&arr[right]>=mid)
right--;
if (left<right)
arr[left++]=arr[right];
while (left<right&&arr[left]<=mid)
left++;
if (left<right)
arr[right--]=arr[left];
}
arr[left]=mid;
Quick_Sort(arr,beginn,left-1);
Quick_Sort(arr,right+1,endn);
}
}
9. 简单选择排序
初见感觉这个算法异常的暴力。核心思想就是遍历一遍找最大值or最小值,重复执行的同时范围也在随之减少(因为每遍历一趟减少了最值),直到数组有序。
概括一下:每一趟在后面 n-i 个待排记录中选取关键字最小的记录作为第 i 个值得记录,两层循环O(n^2)时间复杂度结束
void Simple_Select_Sort(int *arr,int istart,int iend)
{
for (int i=0;i<iend-1;i++)
{
int temp=i;
for (int j=i;j<iend;j++)
if (arr[j]<arr[temp])
temp=j;
swap(arr[temp],arr[i]);
}
}
10. 堆排序
堆有点二叉树的意思,而且我觉得在之前所有基础排序算法之中都是比较难的一种算法。
专门写了篇博客记录一下,顺带学了学怎么做示意图~堆排序简介
void HeapAdjust(int *arr,int top,int range)//arr为数组首地址,top为需要进行恢复的元素下标,range就是范围啦
{
for (int i=top*2;i<=range;i*=2)//为什么是*2?因为要获得子节点的下标
{
if (i<range&&arr[i]<arr[i+1])
i++;//找到两个子节点中最大的元素的下标
if (arr[top]>=arr[i])
break;//不需要交换就退出
swap(arr[top],arr[i]);//较大的子节点上移给父节点
top=i;//现在要处理的点就是子节点
}
}
void InitHeap (int *arr,int length)
{
for (int i=length;i>=1;i--)
arr[i]=arr[i-1];
for (int i=length/2;i>0;i--)
HeapAdjust(arr,i,length);
}
void HeapSort(int *arr,int length)
{
InitHeap(arr,length);
for (int i=length;i>0;i--)
{
swap(arr[i],arr[1]);
HeapAdjust(arr,1,i-1);
}
for (int i=0;i<length;i++)
arr[i]=arr[i+1];
}
PS
int main()
{
int length=20;
int arr[length];
srand((unsigned)time(NULL));
clock_t start = clock(); //时间起始
for (int i=0;i<length;i++)
{
arr[i]=rand()%100;
printf("%5d",arr[i]);
}
printf("
");
ShellSort(arr,length);
clock_t end = clock(); //时间测试结束
cout<<end - start<<endl; //计算打印出运行时间,单位ms
for (int i=0;i<length;i++)
printf("%5d",arr[i]);
return 0;
}