面试题之——常用排序算法

以下排序默认排序效果是从小到大,待排序序列:3,4,63,4,-9,0,1,32,-2

1.冒泡排序

     基本思想:依次交换相邻两个元素,使得大的数据往下沉(或小的数据往上附浮)

                        第一步:比较相邻的两个元素,如果前者比后者大,则交换两元素。否则,不交换。

                        第二步:重复第一步直到最后两个元素比较完成,此时,最大的元素已经在最后面了,此趟排序完成。

                        第三步:去除最后元素,重复上述两步,对最后元素之前的数据进行排序。

                        第四步:每趟排序完成后,大的数据会忘下沉,也就是需要排序的数据会越来越少,直到没有任何一对数据需要排序,排序成功

      排序过程示例:


      代码示例:

public void bullle(int[] array) {
		//双层循环,第一层控制需要排序的趟数
		for(int i=0; i<array.length-1; i++) {
			//第二层,对第一个直到array.length-i-1的数据排序
			for(int j=0; j<array.length-i-1; j++) {
				//前者大于后者,交换元素
				if(array[j]>array[j+1]) {
					int temp = array[j];
					array[j] = array[j+1];
					array[j+1] = temp;
				}
			}
		}
	 }

2.鸡尾酒排序

       基本思想:鸡尾酒排序法相当于双向冒泡排序,在鸡尾酒排序中,在从左向右的方向上,使大的数据往下沉,在回来也就是从右往左的方向上,使小的数据往上浮。

       过程示例:

     代码示例:

public void cocktailSort(int[] array) {
		int temp;
		for(int k=0; k<array.length/2; k++) {
			//使大的数据往下沉
			for(int i=k; i<array.length-k-1; i++) {
				if(array[i]>array[i+1]) {
					temp = array[i];
					array[i] = array[i+1];
					array[i+1] = temp;
				}
			}
			//使小的数据往上浮
			for(int j=array.length-2-k; j>k; j--) {
				if(array[j]<array[j-1]) {
					temp = array[j];
					array[j] = array[j-1];
					array[j-1] = temp;
				}
			}
		}
	}

3.快速排序

        基本思想:通过一趟排序,使得排序序列分为两部分,一部分的所有数据都小于另一部分,然后在按此方法分别对两部分进行排序,整个排序过程可用递归进行

                            第一步:选取一个基准值(一般为待排序列的首元素),并记录,使得 i , j 分别指向首元素和最后一个元素

                            第二步:从右册开始,比较 j 指向元素和基准值的大小,如果大于,j 向前移动一个元素,直到找到一个比基准值小的元素,停止 j 的移动。

                                           此时, 将 j 所指向的元素赋值给 i 所指向的元素,并让 i 向后移动 一 个元素。

                            第三步:从左侧开始,比较 i 指向元素和基准值的大小,如果小于,i 向后移动一个元素,直到找到一个比基准值大的元素,停止 i 的移动。

                                          此时, 将 i 所指向的元素赋值给 j 所指向的元素,并让 j 向前移动 一 个元素。

                            第四步:重复上述步骤,知道 i 和 j 指向同一个元素,并将基准值赋值给i 和 j所指向的元素。

                                          此时,序列已经被基准值分为两部分,左侧所有元素小于基准值,右侧所有的元素大于基准值

                            第五步:使用相同方法,对基准值两侧的序列分别进行排序

       排序过程示例:


       代码示例:

private void quickSort(int[] array, int start, int end) {
		int i = start, j = end;
		int temp = array[start];//记录基准值
		while(i<j) {
			//从右侧开始,找到第一个小于基准值的元素
			while(i<j && array[j]>temp) {
				j--;
			}
			//将j所在位置元素赋值给i所指向的元素,并使i向后移动
			if(i<j) {
				array[i] = array[j];
				i++;
			}
			//从左侧开始,找到第一个大于基准值的元素
			while(i<j && array[i]<temp) {
				i++;
			}
			//将i所在位置元素赋值给j所指向的元素,并使j向前移动
			if(i<j) {
				array[j] = array[i];
				j--;
			}
		}
		//当i>=j时,循环查找结束,将基准值赋值给i所在位置
		array[i] = temp;
		//对基准值分割的两部分进行排序
		if(i-1>start) {
			quickSort(array, start, i-1);
		}
		if(i+1<end) {
			quickSort(array, i+1, end);
		}
	}

4.插入排序

     基本思想:排序序列分为两部分,前一部分是已排序的序列,后一部分为待排序序列。

                          第一步:从待排序序列中选择一个元素,依次比较其和已排序序列中的元素的大小,直到找到一个比它大的元素,并将其插入到这个元素前边

                          第二步:重复上步,直到待排序序列中没有元素了。

     排序过程示例:

 

代码示例:

public void InsertSort(int[] array) {
		for(int i=1; i<array.length; i++) {
			/*
			 * 第一种方法, 从前往后搜索,直到找到比它大的元素
			 * 然后将这个元素往后所有已排序序列中的元素向后移动
			 * */
//			for(int j=0; j<i; j++) {
//				if(array[i]<array[j]) {
//					int temp = array[i];
//					int k = i;
//					while(k>j) {
//						array[k] = array[k-1];
//						k--;
//					}
//					array[j] = temp;
//					break;
//				}
//			}
			/*
			 * 第二种方法,从后往前搜索,直到找到一个比它小的元素
			 * 同样将这个元素往后所有已排序序列中的元素向后移动
			 * */
			int temp = array[i];
			int j = i;
			if(array[j-1]>temp) {
				while(j>=1 && array[j-1]>temp) {
					array[j] = array[j-1];
					j--;
				}
			}
			//将这个元素赋值给相应位置
			array[j] = temp;
		}
	}

5.选择排序

      这个选择排序和插入排序看上去很像,都是从未排序的序列中选择一个元素,然后插入到已排序序列中。不过它们有很大的不同,选择排序是从待排序序列中选择

       一个最小的元素,然后将这个元素插入到已排序序列的最后,这个方法的优点是,不需要频繁的在数组中移动数据,只需要两两交换即可。

    基本思想: 第一步:从待排序序列中通过比较,找到最小的元素,记录其位置和值

                         第二步:将这个元素与待排序序列的第一个元素(也就是已排序序列最后元素的下一个元素)交换值。重复上述两步,直到所有元素已排完。

    排序过程示例:

   代码示例:

           

           public void selectSort(int[] array) {
		for(int i=0; i<array.length-1; i++) {
			int loc = i;
			int min = array[i];
			//在待排序序列中找到最小的元素
			for(int j=i+1; j<array.length; j++) {
				if(min>array[j]) {
					min = array[j];
					loc = j;
				}
			}
			if(loc != i) {
				array[loc] = array[i];
				array[i] = min;
			}
		}
           }

6.归并排序

        基本思想:将待排序序列分为的两部分,然后对这两部分分别排序,最后将两部分按某种方法合并。排序的过程是一个递归的过程。归并法是算法中分治法的一个典型代表。因此,归并排序也分为两部分,分的过程和治(合并)的过程。

        合并使用的方法是:比较两个队列的队首元素,将小的从该队列中移除并插入到新队列的第一个位置,然后在比较两队列的首元素大小,将小的从该队列移除并将其添加到新队列上次添加的元素的后面,重复第二步知道有一个队列为空。将不为空的队列剩下所有的元素依次添加到新队列的最后。

        排序过程示例:

                第一次分割:{3,  4,  63,  2}{-9,  0,  1,  32,  -2}

                下面以分割后的第一部分为例。

                 第二次分割:{{3,4}{63, 2}} 第三次分割:{{{3}{4}}{{63}{2}}}

              合并的过程:第一次合并:{{3,4}{2,63}} 第二次合并:{2,3,4,63}至此,第一部分已经排序完毕,第二部分排序方法相同,为{-9,-2,0,1,32}

                                     最后将两部分合并为:{-9,-2,0,1,2,3,4,32,63}

       代码示例:

private void MergeSort(int[] array, int start, int end) {
		if(start == end) {
			return;
		}
		int middle = (end - start + 1)/2 + start;
		//分的过程
		MergeSort(array, start, middle-1);
		MergeSort(array, middle, end);
		//合并的过程
		merge(array, start, middle, end);
	}
	
	private void merge(int[] array, int start, int middle, int end) {
		int i = start, j = middle, loc = 0;
		int[] copy = new int[end-start+1];
		while(i<middle && j<=end) {
			if(array[i]>array[j]) {
				copy[loc] = array[j];
				j++;
			} else {
				copy[loc] = array[i];
				i++;
			}
			loc++;
		}
		while(i<middle) {
			copy[loc++] = array[i++];
		}
		while(j<=end) {
			copy[loc++] = array[j++];
		}
		for(int k=0; k<copy.length; k++) {
			array[start++] = copy[k];
		}
		copy = null;
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值