1.冒泡法
冒泡排序最好的时间复杂度为 O(n)。
冒泡排序总的平均时间复杂度为 O(n^2)
冒泡排序算法的原理如下:
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。(比较 n-1 趟,每趟 n-1-i 次)
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
void BubbleSort(int arr[],int n)
{
for(int i=0;i<n-1;++i)
{
for(int j=0;j<n-1-i;++j)
{
if(arr[j] > arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
2.直接快速排序
第一趟比较前两个数,然后把第二个数按大小插入到有序表中;
第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;
依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。
内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,
所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,
直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
//方法一
void InsertSort_1(int arr[],int n)
{
for(int i=1;i<n;i++)//循环从第2个元素开始
{
if(arr[i] < arr[i-1])
{
int temp=arr[i];
for(int j=i-1;j>=0 && arr[j]>temp;j--)
arr[j+1]=arr[j];
arr[j+1]=temp;
}
}
}
//方法二
//a[0]哨兵位,假设a[1]已为排好序的,开始排序 //打印从arr[1]开始
void InsertSort_2(int arr[],int n)
{
for(int i=2;i<n;++i)
{
if(arr[i] < arr[i-1])
{
arr[0] = arr[i];
arr[i] = arr[i-1];
for(int j=i-1;arr[0]<arr[j-1];--j)
arr[j] = arr[j-1];
arr[j] = arr[0];
}
}
}
3. 折半插入排序
在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],
末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素小,
则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),
如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]
void BinSort(int arr[],int n)
{
for(int i=2;i<=n;i++)
{
arr[0]=arr[i];
int low=1;
int high=i-1;
while (low<=high)
{
int mid=(low+high)/2;
if(arr[0]<arr[mid])
high=mid-1;
else
low=mid+1;
}
for(int j=i-1;j>=low;j--)
{
arr[i]=arr[j];
i--;
}
arr[low]=arr[0];
}
arr[0] = NULL;
}
4.希尔排序
希尔排序属于插入类排序,是将整个有序序列分割成若干小的子序列分别进行插入排序。
排序过程:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序;
然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止。
void shellSort(int arr[],int n)
{
if(n<=1|| arr==NULL)
return;
for(int div=n/2;div>=1;div=div/2)//定增量div,并不断减小
{
for(int i=0;i<=div;++i)//分组成div组
{
for(int j=i;j<n-div;j+=div)//对每组进行插入排序
for(int k=j;k<n;k+=div)
if(arr[j]>arr[k])
{
int tmp = arr[j];
arr[j] = arr[k];
arr[k] = tmp;
}
}
}
}
5.快速排序
//快速排序
void Qsort(int arr[], int low, int high)
{
if(low >= high)
{
return;
}
int first = low;
int last = high;
int key = arr[first];/*用字表的第一个记录作为枢轴*/
while(first < last)
{
while(first < last && arr[last] >= key)
{
--last;
}
arr[first] = arr[last];/*将比第一个小的移到低端*/
while(first < last && arr[first] <= key)
{
++first;
}
arr[last] = arr[first];
/*将比第一个大的移到高端*/
}
arr[first] = key;/*枢轴记录到位*/
Qsort(arr, low, first-1);
Qsort(arr, first+1, high);
}
6.直接选择排序
第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,
与R[1]交换,....,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,
总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
void SelectSort(int arr[], int n)
{
for (int i = 0; i < n - 1; i++)
{
int m = i;
for (int j = i + 1; j < n; j++)
{
if (arr[j] < arr[m])
m = j;
if (m != i)
{
int tmp = arr[i];
arr[i] = arr[m];
arr[m] = tmp;
}
}
}
}
7.堆排序
//堆排序
void swap(int *a, int *b);
void adjustHeap(int param1,int j, int inNums[]);
void HeapSort(int nums, int inNums[]);
//大根堆进行调整
void adjustHeap(int param1, int j, int inNums[])
{
int temp=inNums[param1];
for (int k=param1*2+1;k<j;k=k*2+1)
{
//如果右边值大于左边值,指向右边
if (k+1<j && inNums[k]< inNums[k+1])
{
k++;
}
//如果子节点大于父节点,将子节点值赋给父节点,并以新的子节点作为父节点(不用进行交换)
if (inNums[k]>temp)
{
inNums[param1]=inNums[k];
param1=k;
}
else
break;
}
//put the value in the final position
inNums[param1]=temp;
}
//堆排序主要算法
void HeapSort(int nums,int inNums[])
{
//1.构建大顶堆
for (int i=nums/2-1;i>=0;i--)
{
//put the value in the final position
adjustHeap(i,nums,inNums);
}
//2.调整堆结构+交换堆顶元素与末尾元素
for (int j=nums-1;j>0;j--)
{
//堆顶元素和末尾元素进行交换
int temp=inNums[0];
inNums[0]=inNums[j];
inNums[j]=temp;
adjustHeap(0,j,inNums);//重新对堆进行调整
}
}
8、归并排序
//归并排序
void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex)
{
int i = startIndex, j=midIndex+1, k = startIndex;
while(i!=midIndex+1 && j!=endIndex+1)
{
if(sourceArr[i] > sourceArr[j])
tempArr[k++] = sourceArr[j++];
else
tempArr[k++] = sourceArr[i++];
}
while(i != midIndex+1)
tempArr[k++] = sourceArr[i++];
while(j != endIndex+1)
tempArr[k++] = sourceArr[j++];
for(i=startIndex; i<=endIndex; i++)
sourceArr[i] = tempArr[i];
}
//内部使用递归
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex)
{
int midIndex;
if(startIndex < endIndex)
{
midIndex = startIndex + (endIndex-startIndex) / 2;//避免溢出int
MergeSort(sourceArr, tempArr, startIndex, midIndex);
MergeSort(sourceArr, tempArr, midIndex+1, endIndex);
Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
}
}
主函数(用于测试)
void main()
{
int arr[] = {6,23,43,12,8,2,31,29};
int n = sizeof(arr)/sizeof(int);
//BubbleSort(arr,n);
//InsertSort_1(arr,n);
//InsertSort_2(arr,n);
//BinSort(arr,n);
//shellSort(arr,n);
//Qsort(arr,0,n);
//SelectSort(arr,n);
//HeapSort(n, arr);
int brr[8];
MergeSort(arr,brr, 0, n-1);
for(int i=0;i<n;i++)
printf("%d ",arr[i]);
printf("\n");
}
#endif