排序(插入排序、希尔排序、堆排序、归并排序、快速排序法)

(1)插入排序

      假设位置0到P-1上的元素是已经排好序的,对于P上的元素,其与0到p-1位置元素比较,找到小于P位置元素j把j+1到p-1元素往后移动一个位置,把p位置元素插入,这样就完成0到p位置元素的排序,依次类推,最终完成排序。

(2)希尔排序

     使用一个增量序列h,每次排序都使得A[i]<A[i+h],h的选择是:h(k)=N/2,h(k+1)=h(k)/2。当h(k)=1时,完成排序。

(3)堆排序

       先把数组元素按堆的顺序存储(采用堆的思想,与堆不同的是结点元素大于或等于儿子结点元素),然后删除最大的(即把最大的依次保存起来,依次放在堆序的最后位置)最后完成排序

(4)归并排序

       思想是合并两个已经排序好的 数据序列,比如:要排序24,13,26,1,2,27,38,25.  将该数组分为2部分:24,13,26,1     2,27,38,25,递归的把前4个后4个采用归并排序进行排序。1,13,24,26      2,25,27,38.将这两个部分合并 1,2,13,15,24,26,27,38最后完成排序。

(5)快速排序法

       1.三数中值法获取枢纽元素V:把left、center、right位置上的元素进行比较,最小的放在left、最大放在right
       2.将枢纽元素与最后一个元素交换
       3.将前面的N-1个元素:小元素移到数组的左边,大元素移到数组的右边,其中大小是相对枢纽元素V而言的
       4.在数组中枢纽前面的元素(s1)都小于枢纽,后面的元素(s2)都大于枢纽
       5.递归的对s1和s2使用同样的方法

例如:8,1,4,9,6,3,5,2,7,0 —>比较left,center,right上元素并交换,找出枢纽元素:0 1 4 9 6 3 5 2 7 8—>枢纽元素为6,把大于6的放在6 后面,小于6的放在其前面,可得        0 1 4 2 5 3 6 9 7 8,6的前部分采用快速排序,后部分采用递归排序。递归结束条件:left+3<=right时,直接采用中值法获取枢纽元素就可以完成排序。

// Algorithm-sorting.cpp : 定义控制台应用程序的入口点。

#include "stdafx.h"
#include<iostream>
using namespace std;
//1.
//插入排序:O(N^2)位置0到位置p的元素是已排过序
void InsertSort(int *&a,int N)
{
	int tem,j;
	for(int i=1;i<N;i++)
	{
		tem=a[i];
		for(j=i;j>0&&tem<a[j-1];j--)
			a[j]=a[j-1];
			a[j]=tem;
	}
}
//2.
//希尔排序:O(N^6/7)选取增量序列,对于每个i我们有A[i]<A[i+h],h的选择是:h(k)=N/2,h(k+1)=h(k)/2,其排序思想用到插入排序
void shellsort(int *&a,int N)
{
	int i,j,h;
	int tem;
	h=1;
	for(h=N/2;h>0;h /=2)
	{
		for(i=h;i<N;i++)
		{
			tem=a[i];
			for(j=i;j>=h;j-=h)
				if(tem<a[j-h])
				a[j]=a[j-h];
				else
					break;
			a[j]=tem;
		}
	}
}
//3.
//*********堆排序:(N*logN)先把数组元素按堆的顺序存储,然后删除最大的
 void buildheap(int *&a,int N)//建立堆
{
	int *max=new int[N+1];
	int hole;
	for(int i=0;i<N;i++)
	{
    hole=i+1;
	for(;hole>1&&a[i]>max[hole/2];hole/=2)
	{
		max[hole]=max[hole/2];
	}
	   max[hole]=a[i];
	}
	for(int i=0;i<N;i++)
	{
		a[i]=max[i+1];
	}
}
void deletemax(int *&a,int N)//删除最大
{
	int tem;
	for(int i=N-1;i>0;i--)
	{
		tem=a[i];
		a[i]=a[0];
		a[0]=tem;
		buildheap(a,i);
	}
}
void Heapsort(int *&a,int N)
{
	buildheap(a,N);
	deletemax(a,N);

}
//4.
/**********归并排序:O(N*logN)合并两个已排序的表,是经典的分治策略
1.将数组打中间(left+right)/2分成2部分
2.
*/
void sort(int *&a,int *&tem,int left,int center,int right)
{
	int leftend=center-1;
	int t=left;
	int num=right-left+1;
	while(left<=leftend&¢er<=right)
		if(a[left]<a[center])
			tem[t++]=a[left++];
		else
			tem[t++]=a[center++];
	while(left<=leftend)
		tem[t++]=a[left++];
	while(center<=right)
		tem[t++]=a[center++];
	for(int i=0;i<num;i++,right--)//此步骤是至关重要的,其保证了a中的子数组调换
		a[right]=tem[right];
}
void Mergesor(int *&a,int *&tem,int left,int right)
{
	int center;
	if(left<right)
	{
		center=(left+right)/2;
		Mergesor(a,tem,left,center);
        Mergesor(a,tem,center+1,right);
		sort(a,tem,left,center+1,right);
	}

}
//5.
/*******快速排序法:O(N*logN)
1.三数中值法获取枢纽元素V:把left、center、right位置上的元素进行比较,最小的放在left、最大放在right
2.将枢纽元素与最后一个元素交换
3.将前面的N-1个元素:小元素移到数组的左边,大元素移到数组的右边,其中大小是相对枢纽元素V而言的
4.在数组中枢纽前面的元素(s1)都小于枢纽,后面的元素(s2)都大于枢纽
5.递归的对s1和s2使用同样的方法
*/
void sw(int &a,int &b)
{
	int tem;
	tem=a;
	a=b;
	b=tem;
}
int media(int *&a,int left,int right)
{
	int center=(left+right)/2;
	if(a[center]<a[left])
		sw(a[left],a[center]);
	if(a[right]<a[left])
		sw(a[left],a[right]);
	if(a[right]<a[center])
		sw(a[center],a[right]);
	sw(a[center],a[right-1]);
	return a[right-1];
}
void Quicksort(int *&a,int left,int right)
{
	if(left<right)
	{
	int m=media(a,left,right);
	if(left+3<=right)          //当子数组长度为3时,sw交换就可以完成排序
	{
	int i=left,j=right-1;
	for(;;)
	{
		while(a[++i]<m){ }
		while(a[--j]>m){ }
		if(i<j)
		sw(a[i],a[j]);
		else
			break;
	}
	sw(a[i],a[right-1]);
	Quicksort(a,left,i-1);
	Quicksort(a,i+1,right);
	}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	int N;
	cout<<"input N:"<<endl;
	cin>>N;
   int* a=new int[N];
	cout<<"input a:"<<endl;
	for(int i=0;i<N;i++)
	{
		cin>>a[i];
	}
	//插入排序
	//InsertSort(a,N);

	//希尔排序
	//shellsort(a, N);

	//堆排序
	//Heapsort(a,N);

	//归并排序
	//int *tem=new int[N];
	//Mergesor(a,tem,0,N-1);

	//快速排序法
	Quicksort(a,0,N-1);
	for(int i=0;i<N;i++)
	{
		cout<<a[i]<<" ";
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值