#三大基础排序:
(注意:跳转里面的插入排序错误)
一、冒泡排序
已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],依此类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。再对a[1]a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]a[n-1]中最大的。再对a[1]~a[n-2]以相同方法处理一轮,依此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。
优点:稳定,比较次数已知;
缺点:慢,每次只能移动相邻两个数据,移动数据的次数多。
二、选择排序
已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[1]与a[3]的值,若a[1]大于a[3]则交换两者的值,否则不变。再比较a[1]与a[4],依此类推,最后比较a[1]与a[n]的值。这样处理一轮后,a[1]的值一定是这组数据中最小的。再将a[2]与a[3]a[n]以相同方法比较一轮,则a[2]的值一定是a[2]a[n]中最小的。再将a[3]与a[4]~a[n]以相同方法比较一轮,依此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。
优点:稳定,比较次数与冒泡排序一样,数据移动次数比冒泡排序少;
缺点:相对之下还是慢。
三、插入排序
已知一组升序排列数据a[1]、a[2]、……a[n],一组无序数据b[1]、b[2]、……b[m],需将二者合并成一个升序数列。首先比较b[1]与a[1]的值,若b[1]大于a[1],则跳过,比较b[1]与a[2]的值,若b[1]仍然大于a[2],则继续跳过,直到b[1]小于a数组中某一数据a[x],则将a[x]a[n]分别向后移动一位,将b[1]插入到原来a[x]的位置这就完成了b[1]的插入。b[2]b[m]用相同方法插入。(若无数组a,可将b[1]当作n=1的数组a)
优点:稳定,快;
缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。
1.冒泡:
算法时间复杂度:O(n2) 外层循环需要比较n-1次,内层循环需要比较n-i次。
public static void popsort(int[] a) {
for (int i = 1; i <= a.length - 1; i++) {// i 第几轮,总共可以取到a.length-1轮
for (int j = 0; j <= a.length - 1 - i; j++) {// 第几轮,能够取到哪个位置
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
2.选择:
时间复杂度:O(n2)
public static void selectsort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i+1; j <a.length; j++) {
if (a[j] > a[i]) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
3.插入:
**算法思想:从数组的第二个元素开始遍历,将该元素与前面的元素比较,如果该元素比前面的元素小,将该元素保存进临时变量中,依次将前面的元素后移,然后将该元 素插入到合适的位置 **
**时间复杂度:O(n2) **
public static void insertsort(int[] a) {
for (int i = 1; i < a.length; i++) {
int temp = a[i];
int j;
for (j = i - 1; j >= 0 && temp < a[j]; j--) {
a[j + 1] = a[j];
}
a[j + 1] = temp;
}
}
其他排序方式:4.归并
4.归并:
思路:先拆分至最低单元,然后再逐一合并---new一个新数组,将合并的前后2个子数组分别装进去,一定注意条件!while(index1<=mid&&index2<=right)其中虽然脚标取到了最后一位,但不能确认,它是否比较过,所以必须有=
public static void s(int[] a, int left, int right) {
int mid = (left + right) / 2;
if (left < right) {
s(a, left, mid);
s(a, mid + 1, right);
ss(a, left, mid, right);
}
}
public static void ss(int[] a, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int index1 = left;
int index2 = mid + 1;
int index = 0;
while (index1 <= mid && index2 <= right) {// 一个数组分成两段,用一个新数组来装
if (a[index1] < a[index2]) {
temp[index++] = a[index1++];
} else {
temp[index++] = a[index2++];
}
} // 一端已经装完 接下来装另一端
while (index1 <= mid) {
temp[index++] = a[index1++];
} // 剩下的装新数组
while (index2 <= right) {
temp[index++] = a[index2++];
}
for (int i = 0; i < temp.length; i++) {// 暂时数组:temp 原数组:a
a[left + i] = temp[i];
}
}