数据结构之排序算法——汇总

排序算法应该是最基础的算法了,博主面试至今没有面试官单就一个排序算法让写个代码什么的。本篇小博先对常见的排序算法进行一下总结,方便日后查看吧。主要内容包括:冒泡排序(快速排序)、选择排序(堆排序)、插入排序(希尔排序)、归并排序。

一、冒泡排序

代码如下:

public static int[] BubbleSort(int[] a) {
		if(a == null || a.length < 2)
			return a;
		for(int i = 0; i < a.length-1; i++) {
			int  flag = 0;
			for(int j = a.length-1; j > i; j--) {
				if(a[j] < a[j-1]) {
					int temp = a[j];
					a[j] = a[j-1];
					a[j-1] = temp;
					flag = 1;
				}
			}
			if(flag == 0)
				break;
		}
		return a;
	}

二、选择排序

思路:两个循环变量i和j,一个最小值指针min,外层循环从0开始,min每次都初始化为i,内层循环j从i+1开始,其性能略优于冒泡排序法,代码如下:

public static int[] SelectSort(int[] a) {
		if(a == null || a.length < 2)
			return a;
		for(int i = 0; i < a.length-1; i++) {
			int min = i;
			boolean change = false;
			for(int j = i+1; j < a.length; j++) {
				if(a[j] < a[min]) {
					min = j;
					change = true;
				}
			}
			if(change) { //a[i]恰好就是当前序列中最小的那个
				int temp = a[i];
				a[i] = a[min];
				a[min] = temp;
			}
		}
		return a;
	}
三、插入排序

思路:遍历数组,将数组后面的数按照顺序插入到正确的位置,代码如下

public static int[] InsertSort(int[] a) {
		if(a == null || a.length < 2)
			return a;
		for(int i = 1; i < a.length; i++) {
			int j = i;
			while(j > 0 && a[j] < a[j-1]) {
				int temp = a[j];
				a[j] = a[j-1];
				a[j-1] = temp;
				j--;
			}
		}
		return a;
	}
四、希尔排序

思路:分组的插入排序,代码如下:

public static int[] ShellSort(int[] a) {
<span style="white-space:pre">		</span>if(a == null || a.length < 2)
<span style="white-space:pre">			</span>return a;
<span style="white-space:pre">		</span>for(int increment = a.length/3; increment > 0; increment /= 3) { //确定增量
<span style="white-space:pre">			</span>for(int i = increment; i < a.length; i+=increment) {
<span style="white-space:pre">				</span>int j = i;
<span style="white-space:pre">				</span>while(j > 0 && a[j] < a[j-increment]) {
<span style="white-space:pre">					</span>int temp = a[j];
<span style="white-space:pre">					</span>a[j] = a[j-increment];
<span style="white-space:pre">					</span>a[j-increment] = temp;
<span style="white-space:pre">					</span>j-=increment;
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
        return a;
<span style="white-space:pre">	</span>}

五、堆排序

关键问题:怎么将一个数列变成为一个大顶堆,其实质就是从下往上、从右到左将每个非终端节点当做根节点,将其和其子树调整成大顶堆,代码如下

public static void HeapAdjust(int[] a, int s, int m) {
<span style="white-space:pre">		</span>int temp = a[s];
<span style="white-space:pre">		</span>for(int i = 2*s+1; i < m; i = i*2+1) { //2*s+1是左孩子的下标
<span style="white-space:pre">			</span>if(i < m && a[i] < a[i+1])         //左孩子 < 右孩子
<span style="white-space:pre">				</span>++i;                           //i就变成了右孩子的下标
<span style="white-space:pre">			</span>if(temp >= a[i])                   //如果根节点大于孩子节点了 break
<span style="white-space:pre">				</span>break;
<span style="white-space:pre">			</span>a[s] = a[i];                       //根节点值变成较大的孩子节点
<span style="white-space:pre">			</span>s = i;                             //下次循环的根节点变成这次的较大孩子节点
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>a[s] = temp;                           //较大孩子节点处的值变成根节点
<span style="white-space:pre">	</span>} //程序本质就是完成根节点与孩子节点的交换,选出最大值作为新的根节点
	public static int[] HeapSort(int[] a) {
		if(a == null || a.length < 2)
			return a;
		for(int i = a.length/2; i > 0; i--) {  //先完成堆创建,最大值跑到根节点
			HeapAdjust(a,i-1,a.length-1);
		}
		for(int i = a.length-1; i > 1; i--) {
			int temp = a[i];
			a[i] = a[0];
			a[0] = temp;
			HeapAdjust(a,0,i-1);
		}
		return a;
	}

六、归并排序

主要用到了合并两个有序数组为一个有序数组,递归调用,代码如下:

public static void merge(int[] nums, int low, int mid, int high) {  
		int[] temp = new int[high - low + 1];  
		int i = low;// 左指针  
		int j = mid + 1;// 右指针  
		int k = 0;  

		// 把较小的数先移到新数组中  
		while (i <= mid && j <= high) {  
			if (nums[i] < nums[j]) {  
				temp[k++] = nums[i++];  
			} else {  
				temp[k++] = nums[j++];  
			}  
		}  

		// 把左边剩余的数移入数组  其实这两个while只会执行一个,因为短的那个i/j已经 >mid/high了
		while (i <= mid) {  
			temp[k++] = nums[i++];  
		}  

		// 把右边边剩余的数移入数组  
		while (j <= high) {  
			temp[k++] = nums[j++];  
		}  

		// 把新数组中的数覆盖nums数组  
		for (int k2 = 0; k2 < temp.length; k2++) {  
			nums[k2 + low] = temp[k2];  
		}  
	}
	public static int[] sort(int[] nums,int low,int high) {
		int mid = (low + high)/2;
		if(low < high) {
			sort(nums, low, mid);  
			sort(nums, mid + 1, high);  
			merge(nums,low,mid,high);
		}
		return nums;
	}
	public static int[] MergeSort(int[] a) {
		if(a == null || a.length < 2) {
			return a;
		}
		return sort(a,0,a.length-1);
	}

七、快速排序

//基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,
    //一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
	//快速排序是不稳定的排序。
	//快速排序的时间复杂度为O(nlogn)。
	//当n较大时使用快排比较好,当序列基本有序时用快排反而不好。
	public static int getMiddle(int[] a,int low,int high) { //完成选取基值,左右选边的过程
		int temp = a[high]; //基值的位置
		while(low < high) {
			while(low < high && a[high] > temp) {
				high--;
			}
			while(low < high && a[low] < temp) {
				low++;
			}
			int t = a[low];
			a[low] = a[high];
			a[high] = t;
		}
		return high;
	}
	public static void qsort(int[] a,int low,int high) {
		if(low < high) {
			int mid = getMiddle(a,low,high);
			qsort(a,low,mid-1);
			qsort(a,mid+1,high);
		}
	}
	public static void quickSort(int[] a,int low,int high) {
		if(a.length > 0) {
			qsort(a,0,a.length-1);
		}
	}
}





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值