高效面试之各种排序算法c实现

/*--------------
author:cqkxboy168
date:2014-8-4
--------------*/
#include <stdio.h>
#include <stdlib.h>
//bitmap使用
#define MAX 200
int map[1+MAX/32]={0};

void swap(int *a,int *b)
{
	int temp=*b;
	*b=*a;
	*a=temp;
}
//选择排序: 
//原理:{有序}[无序],每一次循环从[无序]里面Select一个最小的元素。

void SelectSort(int array[],int len)
{
	int i,j,temp,flag;
	for(i=0;i<len-1;i++)
	{
		temp=array[i];//i是{有序}的结束下标
		flag=i;
		for(j=i+1;j<len;j++)//j的起始值是[无序]的首元素.循环结束后flag是最小值的位置,temp是最小值
		{
			if(array[j]<temp)
			{
				temp=array[j];//重置temp
				flag=j;
			}
		}
		if(flag!=i)
		{
			array[flag]=array[i];//最小记录与{有序}的最后一个交换位置
			array[i]=temp;
		}
	}
}
//插入排序
//原理:{有序}[无序],选取[无序]的第一个元素insert到{有序}应该的位置
void InsertSort(int array[],int len)
{
	int i,j,temp;
	for(i=1;i<len;i++) //i控制[无序]循环,注意此处下标为i=1 
	{
		temp=array[i];//[无序]的第一元素
		for(j=i-1;j>=0;--j) //j控制{有序} 循环,所以j的开始下标为j=i-1
		{
			if(temp<array[j])
			{
				array[j+1]=array[j];
			}
			else
				break;//跳出的位置j的后面就应该是插入的位置
		}
		array[j+1]=temp;
	}
}
//冒泡排序
//原理:相邻元素比较,每一趟选出最大的气泡
void BubbleSort(int array[],int len)
{
	int i,j;
	for(i=0;i<len;i++)
	{
		for(j=0;j<len-i;j++)//从len-i中选出最大的值
		{
			if(array[j]>array[j+1]) //相邻元素比较
				swap(&array[j],&array[j+1]);
		}
	}
}
//归并排序
//原理:递归地把数组折半,当数组只有1个元素时有序,再合并这些有序数组
//合并数组array[frist...mid]和array[mid+1...last]
void Merge(int array[],int frist,int mid,int last)
{
	int i=frist,j=mid+1,k=0;
	int *temp=(int*)malloc(sizeof(int)*last);
	while(i<=mid && j<=last)
	{
		if(array[i]<array[j])
		{
			temp[k++]=array[i++];
		}
		else
		{
			temp[k++]=array[j++];
		}
	}
	while(i<=mid)
		temp[k++]=array[i++];
	while(j<=last)
		temp[k++]=array[j++];
	for(i=0;i<k;i++)
		array[frist+i]=temp[i];

}
void MergeSort(int array[],int frist,int last)
{
	if(frist<last)
	{
		int mid=(frist+last)/2;
		MergeSort(array,frist,mid);
		MergeSort(array,mid+1,last);
		Merge(array,frist,mid,last);
	}
}
//快速排序
//原理:选定支点,通过一趟排序,比支点小都在其左边,比支点大的都在其右边。然后对前半部分和后半部分递归操作,直到数组只有1个元素
void QuickSort(int array[],int frist,int last)
{
	
	if(frist>=last) //递归结束条件,没有这句程序运行错误
		return;
	int i=frist,j=last;
	int index=array[frist];//支点
	while(i<j)
	{
		while(i<j && array[j]<=index) //从右往左找到第一个小于支点的值
			j--;
		if(i<j)
			array[i++]=array[j];//往左区间填值
		while(i<j && array[i]>=index) //从左往右找到第一个大于支点的值
			i++;
		if(i<j)
			array[j--]=array[i];//往右区间填值
	}
	array[i]=index;//左右区间都填好了,填入支点值
	QuickSort(array,frist,i-1);//对左区间递归调用,此刻i=j是支点的位置
	QuickSort(array,i+1,last);
	
}
//希尔排序
//原理:将元素分成多个子序列,对各个子序列进行插入排序
void ShellSort(int array[],int len)
{
	int i,j,k,temp;
	for(k=len/2;k>0;k=k/2)//按步长值划分为多个子序列
	{
		for(i=k;i<len;i++)//子序列插入排序
		{
			temp=array[i];
			for(j=i-k;j>=0;j-=k)
			{
				if(temp<array[j])
				{
					array[j+k]=array[j];
				}
				else
					break;//j为插入点
			}
			array[j+k]=temp;
		}
	}
}
//堆排序
void AdjustMaxHeap(int array[],int pos,int len)
{
	int child;
	for(;2*pos+1<len;pos=child)
	{
		child=pos*2+1;//父节点为pos,则左孩子节点为pos*2+1
		//得到子节点较大者
		if(child<len-1 && array[child+1]>array[child])
			child++;
		if(array[pos]<array[child])
		{
			swap(&array[pos],&array[child]);
		}
		else
			break;

	}
}

void MaxHeapSort(int array[],int len)
{
	int i;//len/2-1是最后一个非叶子节点
	//循环执行后,变为了MaxHeap,array[0]为最大值
	for(i=len/2-1;i>=0;--i)
	{
		AdjustMaxHeap(array,i,len);
	}
	//每次循环取出一个最大值,缩小heap的范围
	for(i=len-1;i>=0;--i)
	{
		swap(&array[i],&array[0]);//保证array[i]为当前最大值
		AdjustMaxHeap(array,0,i);//缩小heap范围
	}
}
//位图排序
void SetBit(int n)
{
	map[n>>5]=map[n>>5] | (1 <<(n&31));//n>>5是32求整,n&31是求32余数
}
int TestBit(int n)
{
	return map[n>>5] & (1<<(n&31));//判断对应位是否为1
}
void BitMapSort(int array[],int len)
{
	int i,k=0;
	for(i=0;i<len;i++)
		SetBit(array[i]);
	for(i=1;i<=MAX;i++)
    {
        if(TestBit(i))
            array[k++]=i;
    }

}
void main()
{
	int array[]={3,5,4,1,2,6};
	//int array[]={6,5,4,3,2,1};
	int len=sizeof(array)/sizeof(int);
	//MaxHeapSort(array,len);
	//BitMapSort(array,len);
	//SelectSort(array,len);
	//InsertSort(array,len);
	//BubbleSort(array,len);
	//MergeSort(array,0,len-1);
	//QuickSort(array,0,len-1);
	ShellSort(array,len);
	for(int i=0;i<len;++i)
	{
		printf("%d ",array[i]);
	}
}
二、性能比较
2.1 稳定性
插入(希尔除外)、冒泡、归并排序
2.2与数组初始顺序关系
选择排序和堆排序
因为:选择排序{有序}[无序],从无序里面选择出最小的数来,都得把[无序]里的元素全部比较一遍。

2.3时间复杂度


二大消耗空间的排序

归并排序,基数排序

一个时间和空间一样的排序

快速排序0(logn)


1、时间复杂度达到O(nlgn) 的排序算法有:快速排序、堆排序、归并排序。

2、上面前四大类排序中,不稳定的排序有:希尔排序、快速排序、堆排序、简单的选择排序。

稳定的排序有:插入排序(除希尔外)、冒泡排序、归并排序。

3、从平均时间性能而言,快速排序最佳,其所需要的时间最少,但快速排序在最坏的情况下,时间性能还不如堆排序和归并排序


所有简单排序和堆排序都是0(1) ,因为需要一个临时变量来交换元素位置,(另外遍历序列时自然少不了用一个变量来做索引)

快速排序为0(logn),要为递归程序执行过程 栈所需的辅助空间 

归并排序空间复杂是O(n),需要一个大小为n的临时数组

归并排序和基数排序所需辅助空间最多,为O(n)

桶排序的空间复杂度不确定


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值