排序算法1---冒泡、插入、希尔排序

1.冒泡排序

  • 思想:在一趟中找到最大值,放到末尾,接着走一趟寻找最大值,放到倒数第二位,循环一直到最后一位。
  • 改进:如果已经排好序,就不需要继续循环了。


public class Solution {
	   // 如果中间已经排好
	   public int[] bubble_sort(int[] arr) {
		   if (arr.length == 0 || arr == null) return null;
		   int count = 0;
		   for (int i = arr.length-1; i > 0; i-- ) {
		   // 如果最优的话只需要在这里走一趟
			   for (int j = 0; j < i; j++) {
				   if (arr[j] > arr[j+1]) {
					   count = 1;
					   swap(arr, j, j+1);
				   }
			   }
			   if (count == 0) break;
		   }    
		   return arr;
	   }
	   public void swap(int[] arr, int i, int j) {
		   int tmp = arr[i];
		   arr[i] = arr[j];
		   arr[j] = tmp;
	   }
	public static void main(String[] args) {
		Solution so = new Solution();
		int[] arr = {5, 4, 3, 2, 1};
		int[] newArr = so.bubble_sort(arr);
		if (newArr == null) return;
		for (int t : newArr) {
			System.out.print(t + " ");
			}	
		}
}

在这里插入图片描述
时间复杂度最优O(n),只需要走一趟,最坏是O(n^2),因为数组是逆序的
它是稳定的,因为遇到相等的数,不改变顺序
用冒泡排序处理单向链表,这种需要交换元素的,是没问题的。

2.插入排序

  • 思想:当插入一个新的元素时,比较大小,如果否合条件,一个个的往后错


public class Solution {
	   // 如果中间已经排好
	   public int[] insert_sort(int[] arr) {
		   if (arr.length == 0 || arr == null) return null;
		   int i = 1, j = 1;
		   for (i = 1; i < arr.length; ++i) {
			   int tmp = arr[i];
			   // 是插入元素和每个之前的元素比大小
			   // 符合要求的就往后移一位
			   // 不符合要求就停止
			   for (j = i; j > 0 && arr[j - 1] > tmp; --j) {
				   	  // 不符合要求是 arr[j-1] <= tmp
					  arr[j] = arr[j - 1];
				  }
			   arr[j] = tmp;
		   }   
		   return arr;
	   }
	   
	public static void main(String[] args) {
		Solution so = new Solution();
		int[] arr = {5, 4, 3, 2, 1};
		int[] newArr = so.insert_sort(arr);
		if (newArr == null) return;
		for (int t : newArr) {
			System.out.print(t + " ");
			}	
		}
}

在这里插入图片描述
时间复杂度最优O(n),只需要走一趟,最坏是O(n^2),因为数组是逆序的
排序算法是稳定的
插入排序不能处理单向链表,其他和冒泡排序差不多。

3、希尔排序

  • 思想:利用一个增量序列,根据设定的间隔远距离交换两个元素,内部使用的是插入排序


public class Solution {
	   // 如果中间已经排好
	   public int[] shell_sort(int[] arr) {
		   if (arr.length == 0 || arr == null) return null;
		   int len = arr.length;
		   int i = len / 2, j = len / 2;
		   for (int k = len / 2; k >=1 ; k /= 2) {
			   // 这里是间隔元素来比
			   for (i = k; i < arr.length; ++i) {
				   int tmp = arr[i];
				   // j >= k, 最后一个元素也是需要计算的
				   for (j = i; j >= k && arr[j - k] > tmp; j -= k) {
					   	  // 不符合要求是 arr[j-1] <= tmp
						  arr[j] = arr[j - k];
					  }
				   arr[j] = tmp;
			   }
		   }
		   return arr;
 }
	 
	public static void main(String[] args) {
		Solution so = new Solution();
		int[] arr = {81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15};
		int[] newArr = so.shell_sort(arr);
		if (newArr == null) return;
		for (int t : newArr) {
			System.out.print(t + " ");
			}	
		}
}

== 时间复杂度为O(nlogn+n^2),所以时间复杂度为 O(n^2)==

  • 如果增量序列不互质,那么希尔排序就不起作用
  • 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的
发布了74 篇原创文章 · 获赞 0 · 访问量 943

猜你喜欢

转载自blog.csdn.net/wuprogrammer/article/details/104855510