算法之七种排序,七种排序


插入排序

public static void insertSort(int[] t){
		for(int i=1; i<t.length; i++){
			//将第i个数提取出来
			int temp = t[i];
			int j;
			for(j=i-1; j>=0 && temp<t[j]; j--){
				//如果提取出来的那个数小于t[j],数据里面的数就往后移。
				t[j+1] = t[j];
			}
			//提取出来的数大于或等于t[j],就插入到t[j]的后一个位置上(即t[j+1])
			t[j+1] = temp;
			
		}
	}

    时间复杂度:最好情况为O(n);   最坏情况为:O(n^2),是稳定的。

希尔排序

public static void shellSort(int[] t){
		//不断缩小比较数据之间的位置,直到变成插入排序
		for(int delta=t.length/2; delta>0; delta/=2){
			//原理和插入排序一样,
			//只是将1换成delta而已
			for(int i=delta; i<t.length; i++){
				int temp=t[i];
				int j;
				for(j=i-delta; j>=0 && temp<t[j]; j-=delta){
					t[j+delta] = t[j];
				}
				t[j+delta] = temp;
			}
		}
	}

    基本思想是分组的直接插入排序。时间复杂度为:O(n(㏒2n)²),那个2是指下标的2(下同),是不稳定的。

冒泡排序

public static void bubbleSort(int[] t){
		//是否交换的标记
		boolean exchange = true;
		//每循环一次,就会得到一个最大值
		for(int i=1; i<t.length && exchange; i++){
			exchange = false;			
			for(int j=0; j<t.length-i; j++){
				if(t[j]>t[j+1]){
					int temp = t[j+1];
					t[j+1] = t[j];
					t[j] = temp;
					exchange = true;
				}
				
			}
			
		}
	}

    基本思想是:比较相邻两个元素的关键字值,如果反序,则交换。如果按升序排序,每一趟将被扫描的数据序列中的最大元素交换到最后位置,就像气泡从水里冒出一样。     时间复杂度:最好情况:O(n);   最坏情况:O(n²),是稳定的

快速排序

	public static void quickSort(int[] t){
		quickSort(t,0,t.length-1);
	}

	private static void quickSort(int[] t, int begin, int end) {
		//判断序列是否有效
		if(begin<end){			
			int i=begin, j=end;
			//提取基准值
			int vot = t[i];
			while(i!=j){
				//从后面寻找较小值
				while(i<j && vot <= t[j]){
					j--;
				}
				if(i<j){
					//较小值往前移动
					t[i++] = t[j];
				}
				//从前面寻找较大值
				while(i<j && t[i]<=vot){
					i++;
				}
				if(i<j){
					//较大值往后移动
					t[j--] = t[i];
				}
			}
			//确定基准值的位置
			t[i]=vot;
			//前端子序列在排序,递归调用
			quickSort(t,begin,j-1);
			//后端子序列在排序,递归调用
			quickSort(t,i+1,end);
			
		}
		
	}

    基本思想是:在数据序列中选择一个值作为比较的基准值,每趟从数据序列的两端开始交替进行,将小于基准值的元素交换到序列前端,将大于基准值的元素交换到序列后端,介于两者之间的位置则成为基准值的最终位置。同时,序列被划分成两个子序列,再用同样的方法分别对两个子序列进行排序,直到子序列的长度为1,则完成排序。     时间复杂度:最好的情况:O(n*㏒2n);   最坏的情况:O(n²);是不稳定的。


直接选择排序

	public static void selectSort(int[] t){
		for(int i=0; i<t.length-1; i++){
			//标记最小值的位标
			int min=i;
			//遍历寻找最小值
			for(int j=i+1; j<t.length; j++){
				if(t[j]<t[min]){
					min=j;
				}
			}
			//将最小值交换到前面
			if(min!=i){
				int temp = t[i];
				t[i] = t[min];
				t[min] = temp;
			}
		}
	}

    基本思想:第一趟从n个元素的数据序列中选出关键字最小(或最大)的元素并放到最前(或最后)位置,下一趟再从n-1个元素中选出最小(大)的元素并放到次前(后)位置。以此类推,经过n-1趟完成排序。     时间复杂度:最好情况:O(n²);    最坏情况:O(n²);    是不稳定的。

堆排序

	//将以begin为根的子树调整成最小堆
	private static void sift(int[] t,int begin, int end){
		//j为i结点的左孩子
		int i=begin, j=2*i+1;
		//子树根节点的值
		int temp=t[i];
		while(j<=end){
			//比较左右孩子,将j定位到最小那个
			if(j<end && t[j]>t[j+1]){
				j++;
			}
			if(temp>t[j]){
				//若子树根节点的值较大,
				//较小的孩子结点上移
				t[i]=t[j];	
				//使i,j向下一层
				i=j;
				j=2*i+1;
			}else{
				break;
			}
		}
		//当前子树的原根值调整后的位置
		t[i]=temp;
	}
	
	public static void heapSort(int[] t){
		int n=t.length;
		//创建最小堆
		for(int j=n/2-1; j>=0; j--){
			sift(t,j,n-1);
		}
		//每趟将最小值交换到后面,再调整成堆
		for(int j=n-1; j>0; j--){
			int temp = t[0];
			t[0] = t[j];
			t[j] = temp;
			sift(t,0,j-1);
		}
	}

    基本思想:首先和直接选择排序对比一下,在直接选择排序中,每趟从数据序列中选出一个最小值交换到前面,其余n-1个元素原地不动,下一趟需要再次比较这些元素,因此直接选择排序算法的重复比较很多。如果每趟能够利用前一趟的比较结果,则会减少一些重复比较,从而提高算法效率。堆排序就是利用完全二叉树的特性,每趟只需遍历树中的一条路径就行了,而不是全部元素。     时间复杂度:最好最坏情况都是:O(n*㏒2n);    是不稳定的。

归并排序

	//对子序列元素的操作,
	//m和r分别是相邻的两个已排序子序列的起始下标,
	//n为子序列的长度
	private static void merge(int[] X, int[] Y, int m, int r, int n){
		int i=m, j=r, k=m;
		//将X中两个相邻子序列归并到Y中
		while(i<r && j<r+n && j<X.length){
			if(X[i] < X[j]){
				//将较小值复制到Y中
				Y[k++] = X[i++];
			}else{
				Y[k++] = X[j++];
			}
		}
		//将前一个子序列剩余元素复制到Y中
		while(i<r){
			Y[k++] = X[i++];
		}
		//将后一个子序列剩余元素复制到Y中
		while(j<r+n && j<X.length){
			Y[k++] = X[j++];
		}
	}
	
	
	//对子序列的操作
	private static void mergepass(int[] X, int[] Y, int n){
		int i = 0;
		
		while(i < X.length-n*2+1){
			merge(X, Y, i, i+n, n);
			i += 2*n;
		}
		//对于剩余不够2n的子序列的操作
		if(i+n < X.length){
			//尽管后一个子序列长度不够n,
			//但还是可以再来一次merge
			merge(X, Y, i, i+n, n);
			
		}else{
			for(int j=i; j<X.length; j++){
				Y[j]=X[j];
			}
			
		}
		
	}
	
	//对数组的操作
	public static void mergeSort(int[] X){
		int[] Y = new int[X.length];
		int n = 1;
		//一次while循环完成两趟并归,
		//数据序列从X到Y,再从Y到X,
		//使排序后的数据序列仍在数组X中
		while(n<X.length){
			mergepass(X,Y,n);
			n*=2;

			mergepass(Y,X,n);
			n*=2;
		}
	}

    基本思想:n个元素的数据序列可看成是由n个长度为1的排序子序列组成,反复讲相邻的两个子序列归并成一个排序的子序列,直到合并成一个序列,则排序完成。     时间复杂度:最好最坏的情况都是:O(n*㏒2n);    是稳定的。


测试方法

public static void main(String[] args) {
		//创建一个数组
		int[] y = new int[10];
		//向数组赋值
		for(int i=0; i<y.length; i++){
			int a = new Random().nextInt(100);
			y[i] = a;
		}
		//执行排序方法
		selectSort(y);
		//打印排序后的数组
		for(int i=0; i<y.length; i++){
			System.out.println(y[i]);
		}
	}


    如果读者有什么更好的建议或疑问,欢迎在下面评论,一起交流进步。微笑






C语言实现七种排序算法的 演示代码

(1)“冒泡法”

冒泡法大家都较熟悉。其原理为从a[0]开始,依次将其和后面的元素比较,若a[0]>a[i],则交换它们,一直比较到a[n]。同理对a[1],a[2],...a[n-1]处理,即完成排序。下面列出其代码:

void bubble(int *a,int n) /*定义两个参数:数组首地址与数组大小*/

{

int i,j,temp;

for(i=0;i<n-1;i++)

for(j=i+1;j<n;j++) /*注意循环的上下限*/

if(a[i]>a[j]) {

temp=a[i];

a[i]=a[j];

a[j]=temp;

}

}

冒泡法原理简单,但其缺点是交换次数多,效率低。

下面介绍一种源自冒泡法但更有效率的方法“选择法”。

(2)“选择法”

选择法循环过程与冒泡法一致,它还定义了记号k=i,然后依次把a[k]同后面元素比较,若a[k]>a[j],则使k=j.最后看看k=i是否还成立,不成立则交换a[k],a[i],这样就比冒泡法省下许多无用的交换,提高了效率。

void choise(int *a,int n)

{

int i,j,k,temp;

for(i=0;i<n-1;i++) {

k=i; /*给记号赋值*/

for(j=i+1;j<n;j++)

if(a[k]>a[j]) k=j; /*是k总是指向最小元素*/

if(i!=k) { /*当k!=i是才交换,否则a[i]即为最小*/

temp=a[i];

a[i]=a[k];

a[k]=temp;

}

}

}

选择法比冒泡法效率更高,但说到高效率,非“快速法”莫属,现在就让我们来了解它。

(3)“快速法”

快速法定义了三个参数,(数组首地址*a,要排序数组起始元素下标i,要排序数组结束元素下标j). 它首先选一个数组元素(一般为a[(i+j)/2],即中间元素)作为参照,把比它小的元素放到它的左边,比它大的放在右边。然后运用递归,在将它左,右两个子数组排序,最后完成整个数组的排序。下面分析其代码:

void quick(int *a,int i,int j)

{

int m,n,temp;

int k;

m=i;

n=j;

k=a[(i+j)/2]; /*选取的参照*/

do {

while(a[m]<k&&m<j) m++; /* 从左到右找比k大的元素*/

while(a[n]>k&&n>i) n--; /* 从右到左找比k小的元素*/

if(m<=n) { /*若找到且满足条件,则交换*/

temp=a[m];

a[m]=a[n];

a[n]=temp;

m++;

n--;

}

}while(m<=n);

if(m<j) quick(a,m,j); /*运用递归*/

if(n>i) quick(a,i,n);

}

(4)“插入法”

插入法是一种比较直观的排序方法。它首先把数组头两个元素排好序,再依次把后面的元素插入适当的位置。把数组元素插完也就完成了排序。

void ins......余下全文>>
 

大量数据用哪种算法排序最好

七种排序算法:冒泡、选择、插入、快速、Bucket、Shell、Heap
其中冒泡是最简单、也是效率最低的一种排序方法,老师要求我们掌握的是选择排序法。
快速排序法可以说是最好的排序算法:首先选一个分界值,把大于分界值和小于分界值的数据分成两部分;对于分开的部分,不断重复这个过程,直到结束。
 

相关内容