排序问题

排序总共分为8种,

插入排序分为直接插入排序和希尔排序

选择排序分为简单排序和堆排序

交换排序分为冒泡排序和快速排序

还有两种归并排序和基数排序

谭浩强书上给了3种排序,起泡法,比较交换法和选择法

1.直接插入排序

void insert_sort(int a[],int n){
	int i,j,temp;
	for(i=1;i<n;i++)
		if(a[i]<a[i-1]){
			temp=a[i];
			for(j=i-1;temp<a[j]&&j>=0;j--)
				a[j+1]=a[j];
			a[++j]=temp;
		}
}

2.希尔排序

void shell_insert(int a[],int n,int d){
	int i,j,temp;
	for(i=d;i<n;i++)
		if(a[i]<a[i-d]){
			temp=a[i];
			for(j=i-d;j>=0&&temp<a[j];j=j-d)
				a[j+d]=a[j];
			a[j+d]=temp;
		}
}
void shell_sort(int a[],int n){
	int d=n/2;
	while(d>0){
		shell_insert(a,n,d);
		d=d/2;
	}
}

3.简单选择排序

void select_sort(int a[],int n){
	int i,j,k,temp;
	for(int i=0;i<n-1;i++){
		k=i;
		for(j=i+1;j<n;j++)
			if(a[j]<a[k]) k=j;
		if(k!=i){
			temp=a[i];
			a[i]=a[k];
			a[k]=temp;
		}
	}
}

4.堆排序  有3点需要注意

  1.heap_adjust()  for(i=k*2;i<n;i=i*2){//此处如果i=0无法实现,k*2

  2.if(a[0]>=a[i]) break;//注意此处要是a[0],如果是a[k]就错了还是7 a[k]值发生了更新

  3.heap_adjust(a,i-1,1);//这里必须是i-1,已经换出去的数不能在参与调整

  4.void heapsort(int a[],int n)中for(i=n-1;i>1;i--){       i>1

void heap_adjust(int a[],int n,int k){//k是待调整的元素的位置 
	int i;
	a[0]=a[k];
	for(i=k*2;i<n;i=i*2){//此处如果i=0无法实现,k*2 
		if(i<n&&a[i]<a[i+1]) i++;
		if(a[0]>=a[i]) break;//注意此处要是a[0],如果是a[k]就错了还是7 
		else{
			a[k]=a[i];
			k=i;
		}	
	}
	a[k]=a[0];
}
void build_heap(int a[],int n){
	for(int i=n/2;i>0;i--)
		heap_adjust(a,n,i);
}
void heap_sort(int a[],int n){//a[0]空出来 
	int i,temp;
	build_heap(a,n);
	for(i=n-1;i>1;i--){
		temp=a[i];
		a[i]=a[1];
		a[1]=temp;
		heap_adjust(a,i-1,1);//这里必须是i-1,已经换出去的数不能在参与调整 
	}
}
int main(){
	int a[8]={0,4,6,2,5,7,1,3};
	//insert_sort(a,7);
	//shell_sort(a,7);
	//select_sort(a,7);
	heap_sort(a,8);
	for(int i=1;i<=7;i++)
		printf("%d  ",a[i]);
	return 0;
} 

补充:

小顶堆:
有N(N>>10000)个整数,求出其中的前K个最大的数。
为了方便测试我就输入10个数字求前4个最大的。
输入:(第一行n,k代表n个数字求k个最大的)
10 4
1 2 3 4 5 6 7 8 9 10
输出:
7 8 9 10

此处n的改变不影响啥,但是要注意一点,i<len这一点很重要,我猜测是因为后面有i+1这是书上的代码,或者在for循环中直接将i<=n改为i<n,此处用的是大顶堆

#include<stdio.h>
void Heap_Adjust(int a[],int n,int k){
	a[0]=a[k];
	for(int i=k*2;i<=n;i=i*2){
		if(i<n&&a[i]<a[i+1]) i++;
		if(a[0]>=a[i]) break;
		else{
			a[k]=a[i];
			k=i;
		}
	}
	a[k]=a[0];
}
void Build_Heap(int a[],int n){
	for(int i=n/2;i>0;i--)
		Heap_Adjust(a,n,i);
}
void Heap_Sort(int a[],int n){
	Build_Heap(a,n);
	for(int i=n;i>1;i--){
		a[0]=a[i];
		a[i]=a[1];
		a[1]=a[0];
		Heap_Adjust(a,i-1,1);
	}
}
int main(){
	int n,k,i;
	scanf("%d %d",&n,&k);
	int a[n+1];
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	Heap_Sort(a,n);
	for(i=n-k+1;i<=n;i++)
		printf("%d ",a[i]);
}

对于此题如果改为小顶堆,需要将Heap_Adjust中的大小比较改为反过来,这样进行堆排序后的数组即为从小到大,针对此题,如下: 

#include<stdio.h>
void Heap_Adjust(int a[],int n,int k){
	a[0]=a[k];
	for(int i=k*2;i<n;i=i*2){
		if(a[i]>a[i+1]) i++;
		if(a[0]<=a[i]) break;
		else{
			a[k]=a[i];
			k=i;
		}
	}
	a[k]=a[0];
}
void Build_Heap(int a[],int n){
	for(int i=n/2;i>0;i--)
		Heap_Adjust(a,n,i);
}
void Heap_Sort(int a[],int n){
	Build_Heap(a,n);
	for(int i=n;i>1;i--){
		a[0]=a[i];
		a[i]=a[1];
		a[1]=a[0];
		Heap_Adjust(a,i-1,1);
	}
}
int main(){
	int n,k,i;
	scanf("%d %d",&n,&k);
	int a[n+1];
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	Heap_Sort(a,n);
	for(i=k;i>=1;i--)
		printf("%d ",a[i]);
}

 

5.冒泡排序

 注意1. i<n-2,这个n-2来自j的取值范围j<n-i-1 n-i-1=1(当j=0时,a[0]和a[1]比较,所以j最小<1,i=n-2,故i<n-1)

         2.j<n-i-1,因为j+1最大取到n-1,则j最大取到n-2

void bubble_sort(int a[],int n){
	int i,j,temp;
	for(i=0;i<n-1;i++)
		for(j=0;j<n-i-1;j++)
			if(a[j]>a[j+1]){
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;	
			}
}

6.快速排序

int partition(int a[],int low,int high){
	int prio=a[low],temp;
	while(low<high){
		while(low<high&&a[high]>=prio) high--;
		temp=a[low];
		a[low]=a[high];
		a[high]=temp;
		while(low<high&&a[low]<=prio) low++;
		temp=a[high];
		prio=a[low];
		a[high]=temp;
	}
	return low;
}
void quick_sort(int a[],int low,int high){
	int mid;
	if(low<high){
		mid=partition(a,low,high);
		quick_sort(a,low,mid-1);
		quick_sort(a,mid+1,high);
	}
}

7.二路归并  要注意一点,在merge中注意最后把临时数组赋给a时,要从left开始,a数组和b数组可能长度不一样,分治思想

void merge(int a[],int left,int right,int mid){
	int b[right-left+1],i=left,j=mid+1,k=0;
	while((i!=mid+1)&&(j!=right+1)){
		if(a[i]<=a[j])
			b[k++]=a[i++];
		else b[k++]=a[j++];
	}
	while(i!=mid+1) b[k++]=a[i++];
	while(j!=right+1) b[k++]=a[j++];
	for(i=0;i<right-left+1;i++)
		a[left+i]=b[i];
}
void merge_sort(int a[],int left,int right){
	if(left<right){
		int mid=(left+right)/2;
		merge_sort(a,left,mid);
		merge_sort(a,mid+1,right);
		merge(a,left,right,mid);
	}
}

8.基排序  不太好整的样子,还要取每一位,不知道咋个办

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值