package com.example.xiongpeng.mysort;
import android.os.Debug;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
//https://www.jianshu.com/p/de327b97a0de
public class MySortArray_SIX extends AppCompatActivity {
public static String TAG = "MySortArray_SIX";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int array[] = {34, 7, 3, 7, 6, 9, 89, 54, 34, 5, 11, 7, 89, 78};
//MyBuble(array);
//MyInsert(array);
//MySelect(array);
//MyShell(array);
//MyGuiBing(array);
MyQuick(array);
PrintArray(array);
}
public void MyBuble(int [] array){
int length = array.length;
boolean sorted = true;
for(int i = 0 ; i < length - 1; i++){// 因为需要重复n躺,所以 i < arr.length
for(int j = 1; j < length - i; j++){
if(array[j] < array[j - 1]){// 如果前第一个数大于后一个数,则交换
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
sorted = false;
}
}
if(sorted == true){//优化,若已是排好顺序的,则退出
break;
}
}
TAG = TAG + " + MyBuble";
/*
1.2 冒泡时间复杂度分析
这里嵌套两层 for 循环,外层循环 n 次;
内层最多时循环 n - 1次、最少循环 0 次,平均循环(n-1)/2;
所以循环体内总的比较交换次数为:n*(n-1) / 2 = (n^2-n)/2
按照计算时间复杂度的规则,去掉常数、去掉最高项系数,其复杂度为O(N^2)
冒泡排序及其复杂度分析
1.3 冒泡排序空间复杂度分析
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度为 O(N);
平均的空间复杂度为O(1)
1.4 稳定性分析
稳定性:排序后对于那些值相同的元素其相对位置没有发生变化
冒泡排序都是相邻元素的比较,当相邻元素相等时并不会交换,因此冒泡排序算法是稳定性算法
*/
}
public void MyInsert(int[] array){
int length = array.length;
for(int i = 1; i < length - 1; i++){
for(int j = i; j > 0; j--){
if(array[j] < array[j - 1]){
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
TAG = TAG + " + MyInsert";
/*
2.2 时间复杂度分析
如上代码。两次for循环,第一层是循环 n 次;
第二层循环中,最好循环 1 次,最坏循环 n 次,平均循环(n-1)/2次
所以总的循环体内比较的平均次数为(n^2-n)/ 2,按照时间复杂度的计算规则,其平均时间时间复杂度为O(N)
2.3 空间复杂度分析
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);
平均的空间复杂度为O(1)
2.5 插入排序的稳定性
由于插入排序也是相邻元素的比较,遇到相等的相邻元素时不会发生交换,也不会造成相等元素之间的相对位置发生变化
*/
}
public void PrintArray(int array[]){
int length = array.length;
String output = "";
for(int i = 0; i < length; i++){
//System.out.print(array[i] + " ");
output = output + array[i] + " ";
}
Log.v(TAG, output);
}
public void MySelect(int[] array){
int length = array.length;
for(int i = 0; i < length; i++){
int minValue = array[i];//每次循环取第一个值作为最小值
int minIndex = i;//最小值下标
for(int j = i + 1; j < length; j++){
if(minValue > array[j]){
minIndex = j;
minValue = array[minIndex];
}
}
//标识已经在无顺序元素里找到比a[i]小的值
if(i != minIndex){
array[minIndex] = array[i];
array[i] = minValue;
}
}
TAG = TAG + " + MySelect";
/*
3.2 选择排序时间复杂度
外层循环 n 次;
内层循环中,最坏循环 n-1 次,最好循环 0 次,平均循环 (n-1)/2 次
整个循环体中循环 (n^2 - n) / 2 次,所以平均时间复杂度为 O(N)
3.3 选择排序空间复杂度
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);
平均的空间复杂度为O(1)
3.5 选择排序的稳定性
选择排序是不稳定的,比如 3 6 3 2 4,第一次外层循环中就会交换第一个元素3和第四个元素2,那么就会导致原序列的两个3的相对位置发生变化
* */
}
public void MyShell(int [] array){//需要加强记忆
int length = array.length;
int gap = length / 2;
while(gap > 0){
for(int i = gap; i < length; i++){// 从数组下标为 gap的元素开始排序
for(int j = i - gap; j >= 0; j = j - gap){// 每个元素只与自己组内的元素进行直接排序,组内相邻元素比较
if(array[j] > array[j + gap]){
int temp = array[j];
array[j] = array[j + gap];
array[j + gap] = temp;
}
}
}
gap = gap / 2;
}
TAG = TAG + " + MyShell";
/*
4.2 希尔排序时间复杂度分析
希尔排序的效率取决于增量值gap的选取,这涉及到数学上尚未解决的难题,但是某些序列中复杂度可以为O(N1.3),当然最好肯定是O(N),最坏是O(N2)
4.3 希尔排序空间复杂度分析
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);
平均的空间复杂度为O(1)
4.5 希尔排序的稳定性
希尔排序并不只是相邻元素的比较,有许多跳跃式的比较,难免会出现相同元素之间的相对位置发生变化,所以希尔排序是不稳定的
* */
}
public void MyGuiBing(int[] array){
MySortGuiBing(array, 0, array.length - 1);
}
public void MySortGuiBing(int[] array, int left, int right){
if(left < right){
//Log.v(TAG, "MySortGuiBing");
int middle = (left + right) / 2;
MySortGuiBing(array, left, middle);
MySortGuiBing(array, middle + 1, right);
MyMerge(array, left, middle, right);
/*
6.2 归并排序时间复杂度分析
因为不管元素在什么情况下都要做这些步骤,所以花销的时间是不变的,所以该算法的最优时间复杂度和最差时间复杂度及平均时间复杂度都是一样的为:O( nlogn )
6.3 归并排序空间复杂度分析
归并的空间复杂度就是那个临时的数组和递归时压入栈的数据占用的空间:n + logn;所以空间复杂度为: O(n)
以时间换空间:网上很多blog分享空间复杂度只有O(1)的归并排序法;因为传统的归并排序所消耗的空间主要是在归并函数(把两个有序的函数合并成一个有序的函数),所以如果要让空间复杂度为 O(1) ,那么也只能在归并函数中做文章了。其主要思想就是借助于快速排序(其实就是相当于归并函数被快速排序函数替换了);这样的方法虽然可以减少内存的消耗,但是却会在时间上带来损失,因为这样时间复杂度却变成了 O(n^2) 了;所以这种方法并不是一个两全其美的idea;
6.4 归并排序的稳定性
归并排序算法中,归并最后到底都是相邻元素之间的比较交换,并不会发生相同元素的相对位置发生变化,故是稳定性算法
* */
}
}
public void MyMerge(int[] array, int left, int middle, int right){
int leftIndex = left;
int rightIndex = middle + 1;
int[] sortedArray = new int[right - left + 1];
int newIndex = 0;
while((leftIndex <= middle) && (rightIndex <= right)){
if(array[leftIndex] <= array[rightIndex]){
sortedArray[newIndex++] = array[leftIndex++];
}else{
sortedArray[newIndex++] = array[rightIndex++];
}
}
while(leftIndex <= middle){
sortedArray[newIndex++] = array[leftIndex++];
}
while(rightIndex <= right){
sortedArray[newIndex++] = array[rightIndex++];
}
int temp = 0;
while((left + temp) <= right){
array[left + temp] = sortedArray[temp];
temp++;
}
}
public void MyQuick(int[] array){
QuickSort(array, 0, array.length - 1);
}
public void QuickSort(int[] array, int left, int right){
if(left < right){
int i = left;
int j = right;
int x = array[i];
while(i < j){
while((i < j) && (array[j] >= x)){
j--;
}
if(i < j){
array[i++] = array[j];
}
while((i < j) && (array[i] <= x)){
i++;
}
if(i < j){
array[j--] = array[i];
}
}
array[i] = x;
QuickSort(array, left, i - 1);
QuickSort(array, i + 1, right);
}
TAG = TAG + " + MyBuble";
/*
7.3 快速排序时间复杂度
在最优的情况下,快速排序算法的时间复杂度为O(NlogN)
在最坏的情况下,待排序的序列为正序或者逆序,快速排序算法的时间复杂度为O(N)
7.4 快速排序空间复杂度
空间复杂度,主要是递归造成的栈空间的使用:
最好情况,递归树的深度为log2n,其空间复杂度也就为O(logn);
最坏情况,需要进行n‐1递归调用,其空间复杂度为O(n);
平均情况,空间复杂度也为O(logn)。
7.6 快速排序的稳定性
快速排序也是跨越式比较及交换数据,易导致相同元素之间的相对位置发生变化,所以快速排序不稳定
* */
}
import android.os.Debug;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
//https://www.jianshu.com/p/de327b97a0de
public class MySortArray_SIX extends AppCompatActivity {
public static String TAG = "MySortArray_SIX";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int array[] = {34, 7, 3, 7, 6, 9, 89, 54, 34, 5, 11, 7, 89, 78};
//MyBuble(array);
//MyInsert(array);
//MySelect(array);
//MyShell(array);
//MyGuiBing(array);
MyQuick(array);
PrintArray(array);
}
public void MyBuble(int [] array){
int length = array.length;
boolean sorted = true;
for(int i = 0 ; i < length - 1; i++){// 因为需要重复n躺,所以 i < arr.length
for(int j = 1; j < length - i; j++){
if(array[j] < array[j - 1]){// 如果前第一个数大于后一个数,则交换
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
sorted = false;
}
}
if(sorted == true){//优化,若已是排好顺序的,则退出
break;
}
}
TAG = TAG + " + MyBuble";
/*
1.2 冒泡时间复杂度分析
这里嵌套两层 for 循环,外层循环 n 次;
内层最多时循环 n - 1次、最少循环 0 次,平均循环(n-1)/2;
所以循环体内总的比较交换次数为:n*(n-1) / 2 = (n^2-n)/2
按照计算时间复杂度的规则,去掉常数、去掉最高项系数,其复杂度为O(N^2)
冒泡排序及其复杂度分析
1.3 冒泡排序空间复杂度分析
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度为 O(N);
平均的空间复杂度为O(1)
1.4 稳定性分析
稳定性:排序后对于那些值相同的元素其相对位置没有发生变化
冒泡排序都是相邻元素的比较,当相邻元素相等时并不会交换,因此冒泡排序算法是稳定性算法
*/
}
public void MyInsert(int[] array){
int length = array.length;
for(int i = 1; i < length - 1; i++){
for(int j = i; j > 0; j--){
if(array[j] < array[j - 1]){
int temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
TAG = TAG + " + MyInsert";
/*
2.2 时间复杂度分析
如上代码。两次for循环,第一层是循环 n 次;
第二层循环中,最好循环 1 次,最坏循环 n 次,平均循环(n-1)/2次
所以总的循环体内比较的平均次数为(n^2-n)/ 2,按照时间复杂度的计算规则,其平均时间时间复杂度为O(N)
2.3 空间复杂度分析
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);
平均的空间复杂度为O(1)
2.5 插入排序的稳定性
由于插入排序也是相邻元素的比较,遇到相等的相邻元素时不会发生交换,也不会造成相等元素之间的相对位置发生变化
*/
}
public void PrintArray(int array[]){
int length = array.length;
String output = "";
for(int i = 0; i < length; i++){
//System.out.print(array[i] + " ");
output = output + array[i] + " ";
}
Log.v(TAG, output);
}
public void MySelect(int[] array){
int length = array.length;
for(int i = 0; i < length; i++){
int minValue = array[i];//每次循环取第一个值作为最小值
int minIndex = i;//最小值下标
for(int j = i + 1; j < length; j++){
if(minValue > array[j]){
minIndex = j;
minValue = array[minIndex];
}
}
//标识已经在无顺序元素里找到比a[i]小的值
if(i != minIndex){
array[minIndex] = array[i];
array[i] = minValue;
}
}
TAG = TAG + " + MySelect";
/*
3.2 选择排序时间复杂度
外层循环 n 次;
内层循环中,最坏循环 n-1 次,最好循环 0 次,平均循环 (n-1)/2 次
整个循环体中循环 (n^2 - n) / 2 次,所以平均时间复杂度为 O(N)
3.3 选择排序空间复杂度
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);
平均的空间复杂度为O(1)
3.5 选择排序的稳定性
选择排序是不稳定的,比如 3 6 3 2 4,第一次外层循环中就会交换第一个元素3和第四个元素2,那么就会导致原序列的两个3的相对位置发生变化
* */
}
public void MyShell(int [] array){//需要加强记忆
int length = array.length;
int gap = length / 2;
while(gap > 0){
for(int i = gap; i < length; i++){// 从数组下标为 gap的元素开始排序
for(int j = i - gap; j >= 0; j = j - gap){// 每个元素只与自己组内的元素进行直接排序,组内相邻元素比较
if(array[j] > array[j + gap]){
int temp = array[j];
array[j] = array[j + gap];
array[j + gap] = temp;
}
}
}
gap = gap / 2;
}
TAG = TAG + " + MyShell";
/*
4.2 希尔排序时间复杂度分析
希尔排序的效率取决于增量值gap的选取,这涉及到数学上尚未解决的难题,但是某些序列中复杂度可以为O(N1.3),当然最好肯定是O(N),最坏是O(N2)
4.3 希尔排序空间复杂度分析
空间复杂度就是在交换元素时那个临时变量所占的内存
最优的空间复杂度为开始元素已排序,则空间复杂度为 0;
最差的空间复杂度为开始元素为逆排序,则空间复杂度最坏时为 O(N);
平均的空间复杂度为O(1)
4.5 希尔排序的稳定性
希尔排序并不只是相邻元素的比较,有许多跳跃式的比较,难免会出现相同元素之间的相对位置发生变化,所以希尔排序是不稳定的
* */
}
public void MyGuiBing(int[] array){
MySortGuiBing(array, 0, array.length - 1);
}
public void MySortGuiBing(int[] array, int left, int right){
if(left < right){
//Log.v(TAG, "MySortGuiBing");
int middle = (left + right) / 2;
MySortGuiBing(array, left, middle);
MySortGuiBing(array, middle + 1, right);
MyMerge(array, left, middle, right);
/*
6.2 归并排序时间复杂度分析
因为不管元素在什么情况下都要做这些步骤,所以花销的时间是不变的,所以该算法的最优时间复杂度和最差时间复杂度及平均时间复杂度都是一样的为:O( nlogn )
6.3 归并排序空间复杂度分析
归并的空间复杂度就是那个临时的数组和递归时压入栈的数据占用的空间:n + logn;所以空间复杂度为: O(n)
以时间换空间:网上很多blog分享空间复杂度只有O(1)的归并排序法;因为传统的归并排序所消耗的空间主要是在归并函数(把两个有序的函数合并成一个有序的函数),所以如果要让空间复杂度为 O(1) ,那么也只能在归并函数中做文章了。其主要思想就是借助于快速排序(其实就是相当于归并函数被快速排序函数替换了);这样的方法虽然可以减少内存的消耗,但是却会在时间上带来损失,因为这样时间复杂度却变成了 O(n^2) 了;所以这种方法并不是一个两全其美的idea;
6.4 归并排序的稳定性
归并排序算法中,归并最后到底都是相邻元素之间的比较交换,并不会发生相同元素的相对位置发生变化,故是稳定性算法
* */
}
}
public void MyMerge(int[] array, int left, int middle, int right){
int leftIndex = left;
int rightIndex = middle + 1;
int[] sortedArray = new int[right - left + 1];
int newIndex = 0;
while((leftIndex <= middle) && (rightIndex <= right)){
if(array[leftIndex] <= array[rightIndex]){
sortedArray[newIndex++] = array[leftIndex++];
}else{
sortedArray[newIndex++] = array[rightIndex++];
}
}
while(leftIndex <= middle){
sortedArray[newIndex++] = array[leftIndex++];
}
while(rightIndex <= right){
sortedArray[newIndex++] = array[rightIndex++];
}
int temp = 0;
while((left + temp) <= right){
array[left + temp] = sortedArray[temp];
temp++;
}
}
public void MyQuick(int[] array){
QuickSort(array, 0, array.length - 1);
}
public void QuickSort(int[] array, int left, int right){
if(left < right){
int i = left;
int j = right;
int x = array[i];
while(i < j){
while((i < j) && (array[j] >= x)){
j--;
}
if(i < j){
array[i++] = array[j];
}
while((i < j) && (array[i] <= x)){
i++;
}
if(i < j){
array[j--] = array[i];
}
}
array[i] = x;
QuickSort(array, left, i - 1);
QuickSort(array, i + 1, right);
}
TAG = TAG + " + MyBuble";
/*
7.3 快速排序时间复杂度
在最优的情况下,快速排序算法的时间复杂度为O(NlogN)
在最坏的情况下,待排序的序列为正序或者逆序,快速排序算法的时间复杂度为O(N)
7.4 快速排序空间复杂度
空间复杂度,主要是递归造成的栈空间的使用:
最好情况,递归树的深度为log2n,其空间复杂度也就为O(logn);
最坏情况,需要进行n‐1递归调用,其空间复杂度为O(n);
平均情况,空间复杂度也为O(logn)。
7.6 快速排序的稳定性
快速排序也是跨越式比较及交换数据,易导致相同元素之间的相对位置发生变化,所以快速排序不稳定
* */
}
}
代码自己手写,有误之处请指正
参考://https://www.jianshu.com/p/de327b97a0de