最近的博文都是本人最近笔试面试总结,很有参考性,特别是对在杭州的IT企业。
针对笔试面试经常考四种排序:冒泡排序、快速排序、插入排序、选择排序,现作总结。有的笔试题还涉及到对排序理解,如基本有序,用哪种效率更高。
一直用c实现,c写的程序也比较多,java写的少,且还是仿照,导致连面试笔试用java写东西都不敢,于是乎,这里分别用java和c都实现了。
这篇是C实现,还有一博文用java实现,c/java语法有些相似,有些直接拷贝后,稍微修改就ok。算法实现过程备注,主要在C代码中注明,java中就不罗嗦了。
代码纯本人(sprying)手动码的,也是对算法一个小小总结。
/**
*关于排序方法的选择:
* (1)若n较小(如n≤50),可采用直接插入或直接选择排序。
* 当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜。
* (2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;
* (3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序
*/
#include<stdio.h>
void BubbleSort(int a[],int len);
void BubbleSort_1(int *a,int len);
void BubbleSort_2(int a[],int len);
void QuickSort(int a[],int len);
void InsertSort(int a[],int len);
void SelectSort(int a[],int len);//结尾先排好
void SelectSort_1(int a[],int len);//开头先排好
void quickSort_1(int array[],int low,int high);
int Search_Bin(int a[],int len,int key);
void main()
{
int a[10]={10,54,48,28,79,33,54,9,66,72};
for(int i=0;i<10;i++)
printf("a[%d]:%d\t",i,a[i]);
quickSort_1(a,0,9);
for(i=0;i<10;i++)
printf("a[%d]:%d\t",i,a[i]);
printf("66:%d\n",Search_Bin(a,10,66));
}
/**
*冒泡排序
*比较次数O(n^2),n^2/2;交换次数O(n^2),n^2/4,时间复杂度O(n^2)
*/
void BubbleSort(int a[],int len)//轻的浮上
{
int i,j,mark;//mark标记第i趟排序后数组是否有序
int temp;
for(i=0;i<len-1;i++)//从0到len-2趟排序
{
mark=0;
for(j=len-1;j>i;j--)//第i趟排序,相邻两两数比较,,比较次数为len-1-i,如有需要则进行交换,每完成一次循环就将最小元素排在最前
if(a[j]<a[j-1])将相邻两个数进行比较,较小的数往前冒泡
{
temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
mark=1;
}
if(mark==0)//第i趟数列本身有序,不用再进行i+1趟排序
break;//or return;
}
}
void BubbleSort_1(int *a,int len)//*a用法
{
BubbleSort(a,len);
}
void BubbleSort_2(int a[],int len)//重的浮下
{
int i,j,mark;
int temp;
for(i=0;i<len-1;i++)
{
mark=0;
for(j=0;j<len-1-i;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
mark=1;
}
}
if(mark==0)
return;
}
}
/**
* 选择排序,稳定的
* 方法:每一趟从待排序的数据元素中选出最小(或最大)的一个元素, 顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
* 比较次数O(n^2),n^2/2,交换次数O(n),n.,所以选择排序比冒泡排序快
* 时间复杂度为O(n^2) 空间复杂度为O(1)
* 去掉注释外的//,可以显示排序每步的步骤
*/
void SelectSort(int a[],int len)//选择最大的数,放在数列末尾
{
int i,j,mark,temp;
for(i=0;i<len-1;i++)//趟数
{
mark=0;//注意不能为mark=i
//printf("第%d趟,初始mark=%d\t",i+1,mark);
for(j=1;j<len-i;j++)
if(a[j]>a[mark])
mark=j;
//printf("比较之后,mark=%d,(j-1)=%d\t",mark,j-1);
//printf("a[%d]=%d,a[%d]=%d\n",mark,a[mark],j-1,a[j-1]);
if(mark!=0)
{
temp=a[mark];
a[mark]=a[j-1];
a[j-1]=temp;
}
//for(int k=0;k<10;k++)
//printf("a[%d]:%d\t",k,a[k]);
}
//printf("\n");
}
void SelectSort_1(int a[],int len)//选择最小的数,从数列前面放起
{
int i,j,mark,temp;
for(i=0;i<len-1;i++)//趟数
{
mark=i;
//printf("第%d趟,初始mark=%d\t",i+1,mark);
for(j=i+1;j<len;j++)
if(a[j]<a[mark])
mark=j;
//printf("比较之后,mark=%d,(j-1)=%d\t",mark,j-1);
//printf("a[%d]=%d,a[%d]=%d\n",mark,a[mark],j-1,a[j-1]);
if(mark!=i)
{
temp=a[mark];
a[mark]=a[i];
a[i]=temp;
}
//for(int k=0;k<10;k++)
//printf("a[%d]:%d\t",k,a[k]);
}
//printf("\n");
}
/**
* 插入排序,时间复杂度O(n^2)
* 比较次数O(n^2),n^2/4
* 复制次数O(n),n^2/4
* 比较次数是前两者的一半,而复制所需的CPU时间较交换少,所以性能上比冒泡排序提高一倍多,而比选择排序也要快。
*/
void InsertSort(int a[],int len)//插入排序,时间复杂度O(n^2)
{
int i,j,temp;
for(i=1;i<len;i++)
if(a[i]<a[i-1])
{
temp=a[i];
a[i]=a[i-1];
for(j=i-1;(j>0)&&(temp<a[j-1]);j--)
a[j]=a[j-1];
a[j]=temp;
}
}
/**
*快速查找,四种查找中唯一不稳定查找,
*quickSort_1(...)在一个函数中实现快速查找。
*Partition(...)QSort(...)QuickSort(...)三个函数一起实现快速查找,其中奥妙,读者自己摸索学习吧
*/
int Partition(int a[],int low,int high)
{
int pivotKey=a[low];
int temp=a[low];
while(low<high)
{
while((low<high)&&(pivotKey<a[high]))
high--;
if(low<high)
{
a[low]=a[high];
low++;
}
while((low<high)&&(pivotKey>a[low]))
low++;
if(low<high)
{
a[high]=a[low];
high--;
}
}
a[low]=temp;
return low;
}
void QSort(int a[],int low,int high)
{
if(low<high)
{
int i=Partition(a,low,high);
QSort(a,low,i-1);
QSort(a,i+1,high);
}
}
void QuickSort(int a[],int len)//快速排序,时间复杂度O(nlogn),空间复杂度O(nlogn)~O(n),不稳定
{
QSort(a,0,len-1);
}
void quickSort_1(int array[],int low,int high)
{
int pivot,i,j;
if(low<high)
{
i=low;
j=high;
pivot=array[i];
while(i<j)
{
while(i<j&&(pivot<=array[j]))
j--;
if(i<j){
array[i]=array[j];
i++;
}
while(i<j&&(pivot>=array[i]))
i++;
if(i<j){
array[j]=array[i];
j--;
}
}
array[i]=pivot;
quickSort_1(array,low,i-1);//注意i--不行
quickSort_1(array,i+1,high);//注意i++不行
}
}
/**
*折半查找,查找线性表必须是有序列表
*/
int Search_Bin(int a[],int len,int key)
{
int low=0,high=len-1,mid;
while(low<=high)
{
mid=(low+high)/2;
if(key==a[mid])
return mid;
else if(key<a[mid])
high=mid-1;
else
low=mid+1;
}
return -1;//表示不存在这个值
}