意识到自己的C语言功底薄弱,还是得多敲代码
几大排序算法的分析:
代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_LEN 10
void Swap(int *a,int i,int j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
void Print(int *a)
{
for(int i=0;i<MAX_LEN;i++)
{
printf("%d ",a[i]);
}
}
//冒泡排序,相邻两个元素交换,效率 O(n²),适用于排序小列表
void BubbleSort(int *a)
{
int i,j;
int flag= 1;
for(i=0;i<MAX_LEN-1;i++){
for(j=0;j<MAX_LEN-1;j++){
if(a[j]>a[j+1])
Swap(a,j,j+1);
flag = 0;
}
if(flag) break;
}
}
//选择排序,每次将最大/最小排在指定位置,效率O(n²),适用于排序小的列表。
void SelectSort(int *a)
{
int i,j;
int minIndex=0;
for(i=0;i<MAX_LEN;i++)
{
minIndex = i;
for(j=i+1;j<MAX_LEN;j++)
{
if(a[j] < a[minIndex])
{
minIndex = j;
}
}
if(a[minIndex] < a[i])
{
Swap(a,minIndex,i);
}
}
}
//插入排序,最佳效率O(n);最糟效率O(n²)与冒泡、选择相同,适用于排序小列表
//若列表基本有序,则插入排序比冒泡、选择更有效率。
void InsertSort(int *a)
{
int temp,i,j;
for(i=1;i<MAX_LEN;i++)
{
temp = a[i];
j = i-1;
while(j>=0 && a[j] > temp)
{
a[j+1] = a[j];
j--;
}
a[j+1] = temp;
}
}
//希尔排序——缩小增量,排序效率估计O(nlog2^n)~O(n^1.5),取决于增量值的最初大小。
//建议使用质数作为增量值,因为如果增量值是2的幂,则在下一个通道中会再次比较相同的元素。
//希尔排序改进了插入排序,减少了比较的次数。是不稳定的排序,因为排序过程中元素可能会前后跳跃。
void ShellSort(int *a)
{
int gap = 1;
while(gap < MAX_LEN/3)
{
gap = gap * 3 + 1;
}
int temp = 0;
int j = 0;
while(gap>=1)
{
for(int i = gap; i < MAX_LEN; i++)
{
temp = a[i];
for(j=i; j>=gap && a[j-gap] >= temp; j-=gap)
{
a[j] = a[j-gap];
}
a[j] = temp;
}
gap = (gap-1)/3;
}
}
//归并效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。
//适用于排序大列表,基于分治法。
//缺点是占用内存,空间复杂度为T(n)
void Merge(int *a,int left,int mid,int right,int *temp)
{
int i = left;
int j = mid+1;
int k = left;
while(i <= mid && j <= right)
{
if(a[i] < a[j])
{
temp[k++] = a[i++];
}
else
{
temp[k++] = a[j++];
}
}
while(i<=mid)
{
temp[k++] = a[i++];
}
while(j<=right)
{
temp[k++] = a[j++];
}
memcpy(a+left,temp+left,sizeof(int)*(right-left+1));
}
void MergeSort(int *a,int left,int right,int *temp)
{
int mid=0;
if(left<right)
{
mid = left + (right - left)/2;
MergeSort(a,left,mid,temp); //divide 分
MergeSort(a,mid+1,right,temp); //divide 分
Merge(a,left,mid,right,temp); //conquer 治
}
}
//平均效率O(nlogn),适用于排序大列表。
//此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。
//若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。
//基于分治法。
void QuickSort(int *a,int left,int right,int len)
{
int l,r,base;
if(left>right)
return;
l = left;
r = right;
base = a[left];
while(l<r)
{
//因为基准轴在左,所以右边先走
//右边找小于基准轴的值
while(a[r] >= base && l<r)
{
r--;
}
//左边找大于基准轴的值
while(a[l] <= base && l<r)
{
l++;
}
//交换两个值
if(l<r)
{
Swap(a,l,r);
}
}
//将l跟r相遇的值与基准轴的值交换
a[left] = a[l];
a[l] = base;
//递归左边剩下的数
if(left <= l-1)
QuickSort(a,left,l-1,len);
//递归右边剩下的数
if(right>= r+1)
QuickSort(a,r+1,right,len);
return;
}
int main(void)
{
int a[MAX_LEN] = {10,4,6,1,3,5,6,7,9,6};
int len = sizeof(a)/sizeof(a[0]);
//int *temp = (int *)malloc(sizeof(int)*len); //归并排序辅助空间
//BubbleSort(a);
//SelectSort(a);
//InsertSort(a);
//ShellSort(a);
//MergeSort(a,0,len-1,temp);
//free(temp); //释放归并排序的辅助空间
QuickSort(a,0,len-1,len);
Print(a);
return 0;
}
(加油)