几种常用的排序算法(Java实现)

1.直接插入排序

public static void insertSort(int[] a) {
	int length = a.length;//数组长度(提高速度)
	int insertNum;//要插入的数
	for (int i = 1; i < length; i++) {
		insertNum = a[i];
		int j = i-1;//已经排序好的元素个数
		while (j >= 0 && a[j] > insertNum) {
			a[j+1] = a[j];//元素移动一格
			j--;
		}
		a[j+1] = insertNum;//将需要插入的数放在要插入的位置
	}
}

2.归并排序

void mergearray(int a[], int first, int mid, int last, int temp[])
{
    int i = first, j = mid + 1;
    int m = mid,   n = last;
    int k = 0;
 
    while (i <= m && j <= n)
    {
        if (a[i] <= a[j])
            temp[k++] = a[i++];
        else
            temp[k++] = a[j++];
    }
 
    while (i <= m)
        temp[k++] = a[i++];
 
    while (j <= n)
        temp[k++] = a[j++];
 
    for (i = 0; i < k; i++)
        a[first + i] = temp[i];
}
void merge_sort(int a[], int first, int last, int temp[])
{
    if (first < last)
    {
        int mid = (first + last) / 2;
        merge_sort(a, first, mid, temp);    //左边有序
        merge_sort(a, mid + 1, last, temp); //右边有序
        mergearray(a, first, mid, last, temp); //再将二个有序数列合并
    }

3.快速排序

public static void quickSort(int[] a, int left, int right) {
		int i = left, j = right;
		int temp = a[left];//取第一个元素作为标准数据元素
		while (i < j) {
			//在数组右端扫描
			while (i < j && temp <= a[j]) {
				j--;
			}
			if (i < j) {
				a[i++] = a[j];
			}
			//在数组左端扫描
			while (i < j && temp > a[i]) {
				i++;
			}
			if (i < j) {
				a[j--] = a[i];
			}
		}
		a[i] = temp;
		//对左端集合排序
		if (left < i) {
			quickSort(a, left, i-1);
		}
		//对右端集合排序
		if (i < right) {
			quickSort(a, j+1, right);
		}	
	}

4.选择排序

public static void selectSort(int[] a) {
	int length = a.length;
	for (int i = 0; i < length; i++) {//循环次数
		int key = a[i];
		int position = i;
		for (int j = i+1; j < length; j++) {//选出最小的值和位置
			if (a[j] < key) {
				key = a[j];
				position = j;
			}
		}
		a[position] = a[i];//交换位置
		a[i] = key;
	}
}

5.希尔排序

void shellSort(int a[])
	{
	    int j, temp; //d为增量
	    for(int d = a.length/2;d >= 1;d = d/2) //增量递减到1使完成排序
	    {
	        for(int i = d; i < a.length;i++)   //插入排序的一轮
	        {
	            temp = a[i];
	            for(j = i - d;(j >= 0) && (a[j] > temp);j = j-d)
	            {
	                a[j + d] = a[j];
	            }
	        a[j + d] = temp;
	        }
	    }
	} 

或者

public void shellSort(int[] a){
		int d = a.length;
		while (d != 0) {
			d = d/2;
			for (int x = 0; x < d; x++) {//分的组数
				for (int i = x+d; i < a.length; i+=d) {//组中的元素,从第二个数字开始
					int j = i - d;//有序序列最后一位的位数
					int temp = a[i];//要插入的元素
					//从后往前遍历
					for (; j >= 0 && temp < a[j]; j-=d) {
						a[j+d] = a[j];
					}
					a[j+d] = temp;
				}
			}
		}
	}

6.冒泡排序

public void BubbleSort(int[] a) {
		int temp;
		for (int i = 0; i < a.length - 1; i++) {
			for (int j = 0; j < a.length - i -1; j++) {
				if (a[j] > a[j+1]) {
					temp = a[j];//升序
					a[j] = a[j+1];
					a[j+1] = temp;
				}
			}
		}
	}

优化后的冒泡排序

/**
	 * 优化一:如果某一轮两两比较中没有任何元素交换,这说明已经都排好序了
	 * ,算法结束,可以使用一个Flag做标记,默认为false,如果发生交互则
	 * 置为true,每轮结束时检测Flag,如果为true则继续,如果为false则返回。
	 * /
	public void bubbleSort(int[] nums) {
	if (nums == null || nums.length<=1) {
		return;
	}
	//使用一个数记录尾边界
	int length = nums.length;
	boolean flag = true;//发生交换为true,否组false,第一次默认为true
	while (flag) {
		flag = false;//每次开始,设置其为未排序过
		for (int i = 0; i < length; i++) {
			if (nums[i-1] > nums[i]) {
				int temp = nums[i-1];
				nums[i-1] = nums[i];
				nums[i] = temp;
				//表示交换过数据
				flag = true;
			}
		}
		length--;//减小排序尾边界
	}
}

进一步优化后的冒泡
优化二:某一轮结束位置为j,但是这一轮的最后一次交换发生在lastSwap的位置,
则lastSwap到j之间是排好序的,下一轮的结束点就不必是j–了
,而直接到lastSwap即可

public void bubbleSort(int[] nums) {
		int j,k;
		int flag = nums.length;//记录最后交换的位置(尾边界)
		while (flag > 0) {//排序未结束
			k = flag;//k记录尾边界
			flag = 0;
			for (j = 1; j < k; j++) {
				if (nums[j-1]>nums[j]) {
					int temp = nums[j-1];
					nums[j-1] = nums[j];
					nums[j] = temp;
					//表示交换过数据
					flag = j;//记录最新尾边界
				}
			}
		}
	}

7.堆排序(基于完全二叉树左子树当前父节点*2+1, 右子树当前父节点*2+26)

/*
	 * * @param array 完全二叉树
	 * @param h 当前父节点位置
	 * @param size 节点总数
	 */
	public void createHeap(int[] a, int n, int h) {
		int i, j, flag, temp;
		i = h;  //i为要建堆的二叉树根节点下标
		j = 2 * i + 1;//j为i的左孩子节点的下标
		temp = a[i];
		flag = 0;
		//沿左右孩子中值较大者重复向下筛选
		while (j < n && flag != 1) {
			//寻找左右孩子中的较大者
			if (j < n-1 && a[j]<a[j+1] ) {
				j++;
			}
			if (temp > a[j]) {
				flag = 1;//标记结束,筛选条件
			}else {  //否则把a[j]上移
				a[i] = a[j];
				i = j;
				j = 2 *i + 1;
			}
		}
		a[i] = temp;
	}
	public void initCreateHeap(int[] a, int n) {
		//把数组元素a[0]~a[n-1]初始化创建为最大对
		for (int i = (n-2)/2; i >= 0; i--) {
			createHeap(a, n, i);
		}
	}
	public void heapSort(int[] a, int n){
		//用堆排序对数组元素a[0]~a[n-1]进行排序
		int temp; 
		initCreateHeap(a, n);//初始创建最大对
		for (int i = n - 1; i > 0; i--) {//当前最大对每次个数-1
			//吧栈顶a[0]元素和当前最大对最后一个元素交换
			temp = a[0];
			a[0] = a[i];
			a[i] = temp;
			createHeap(a, i, 0);//调整根节点(下标为0,自二叉树个数为i)满足最大对
		}
	}
  1. 桶排序(基数排序):
public static void sort(int[] a) {
		//首先确定排序的躺输
		int max = a[0];
		for (int i = 1; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
			}
		}
		int time = 0;
		//判断位数
		while (max > 0) {
			max/=10;
			time++;
		}
		//建立10个队列
		List<ArrayList> queue = new ArrayList<>();
		for (int i = 0; i < 10; i++) {
			ArrayList<Integer> queue1 = new ArrayList<>();
			queue.add(queue1);
		}
		//进行time次分配和收集
		for (int i = 0; i < time; i++) {
			//分配数组元素
			for (int j = 0; j < a.length; j++) {
				//得到数字的第time+1位数
				int x = a[j] %(int)Math.pow(10, i+1)/(int)Math.pow(10, i);
				ArrayList<Integer> queue2 = new ArrayList<>();
				queue2.add(a[j]);
				queue.set(x, queue2);
			}
			int count = 0;//元素计数器
			for (int k = 0; k < 10; k++) {
				while (queue.get(k).size()>0) {
					ArrayList<Integer> queue3 = new ArrayList<>();
					a[count] = queue3.get(0);
					queue3.remove(0);
					count++;
				}
			}
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值