/**
目的:数组的基本操作
创建及初始化:数组的大小 1、声明时初始化;2、new 分配空间大小, 声明时不能指定数组大小如int a[4];
一维数组的创建方式:
int a[]; a = new int[5]; //动态初始化
int[] a, b; //创建a,b两个数组
int a[] = {1, 2, 3, 4}; //静态初始化
int a[] = new int[5]; //分配空间,只有分配了空间才能进行访问
多维数组:
int[][] a = {{1},
{1, 2},
{1, 2, 3},
{1, 2, 3, 4}};//不指定数组的大小
int a[][] = new int[4][5];
数组常用操作:
1、排序(默认按从小到大排序)
关于排序详细介绍见:http://blog.163.com/a_573801550/blog/static/197629116201110254755462/ c语言
默认:整型数组 ,以下按从小到大进行排序,数组有效下标从0开始
检验一个排序算法是否能满足所有情况(在符合输入条件的范围内)最好的测试数据就是:逆序输入待排数据
1、冒泡排序:
思想:相邻值比较,如果a[i] < a[i+1] 则将两个值进行交换,每次排序大的数据往后,小的数据往前移。
每次确定一个数据,和选择排序有相似之处
最好情况:当数组是小到大有序时,只需比较,没有交换
最坏情况:当数组是大到小有序时,次次交换,n(n-1)/2,时间最多
改进:可以设置一标识,若一次扫描中没有进行一次交换则表示是有序的
外层循环次数:每趟排序能将剩余数据中最大的数据放到末尾,即每次确定一个数据,所以需要(length-1)次
内层循环次数:比较是前后比较,即a[i] 与 a[i+1]所以要保证数组不能越界;因为每趟都能确定一个数据,
所以每次内层的循环次数都会减去1(这个结合外层参数进行控制)
2、选择排序:
思想:选择剩余数据中的最小值下标值;将其值与剩余数据中最前面值进行交换 O(n^2)
外层循环次数的确定类似冒泡排序
3、快排
思想:快排用到的是分治思想。找到一个分界值,其值左边都比改值小,右边都比改值大。平均情况 O(N(logN))
关键:找出分界值 ,分界值的选取方式决定着时间复杂度大小
1、每次查找分界值开始时将待查数组的首下标作为分界值(当逆序时 O(n^2))
2、每次随机从待查数组中选取分界值
4、直接插入排序
思想:每次插入的序列都是已经排好序的
1、将待插入值 a[i] 与前一个值 a[i-1] 进行比较,若a[i] > a[i-1],则不动,若a[i] < a[i-1]
2、临时存储temp = a[i]; a[i] = a[i-1]
3、再将temp与前面有序值从后往前依次比较,若值大于temp,则向后移动
4、将temp的值插入进去
外层循环次数:因每次确定一个数据,所以共需(length - 1)次
内层循环次数:与排序好数据中比插入数据大的个数
2、其它想到再写吧
*/
import java.util.Random; import java.util.Arrays; class ArrayOperation { public static void main(String[] args){ //int a[] = {3254, 231, 425675, 4325, 6565, 34, 45675, 434, 2, 342}; int a[] = {5, 4, 3, 2, 1}; /*int a[] = new int[10]; Random random = new Random(); for (int i = 0; i < a.length; ++i){ //a[i] = (int)(Math.random() * 100); //产生0-100间的随机整数,牵涉到强制类型转换,耗时 a[i] = random.nextInt(100); //产生0-100间的随机整数 }*/ for (int i = 0; i < a.length; ++i){ System.out.print(a[i] + "\t"); } System.out.println(); //Arrays.sort(a); //java包中快排方法:java.util.Arrays->java.util.DualPivotQuicksort Sort sort = new Sort(); //sort.selectSort(a); //sort.selectSort1(a); //sort.bubbleSort(a); //sort.qSort(a, 0, a.length-1); sort.insertSort(a); for (int i = 0; i < a.length; ++i){ System.out.print(a[i] + "\t"); } } } class Sort { private int num = 0; //记录循环次数 /*冒泡排序: 外层循环次数: */ void bubbleSort(int[] a){ /*for (int i = 1; i < a.length; ++i){ boolean flag = true; for (int j = 0; j < a.length-i; ++j){// if (a[j] > a[j+1]){ int temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; flag = false; num += 3; //a[i] = a[i] + a[j]; a[j] = a[i] - a[j]; a[j] = a[i] - a[j]; } } if (flag){ break; } }*/ //下面的写法或许更好理解 int time = a.length; for (int i = 0; i < a.length-1; ++i){ boolean flag = true; time--; for (int j = 0; j < time; ++j) { if (a[j] > a[j+1]){ int temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; flag = false; num += 3; } } if (flag){ break; } } System.out.println("冒泡排序:" + num); } //选择排序 void selectSort(int[] a){ for (int i = 0; i < a.length-1; ++i){ int minIndex = i; //最小索引值 for (int j = i+1; j < a.length; ++j){ if (a[j] < a[minIndex]){/ minIndex = j;/记录最小索引值 num ++; } } if (i != minIndex){ //若i == minIndex 则表示当前数即为最小数,不需要进行交换 int temp = a[i]; a[i] = a[minIndex]; a[minIndex] = temp; num += 3; } } System.out.println("选择排序交换次数:" + num); } /*void selectSort1(int[] a){ for (int i = 0; i < a.length-1; ++i) { for (int j = i+1; j < a.length; ++j) { if (a[i] > a[j]) { int temp = a[i]; a[i] = a[j]; a[j] = temp; num += 3; } } } System.out.println("次数:" + num); }*/ /* fun: 找出快排分界值 @param: a 排序数组 @param: low 待排数组最低下标 @param: high 待排数组最高下标 @return: 分界值下标 */ int position(int[] a, int low, int high){ int pKey = a[low]; while (low < high){ while (low < high && a[high] >= pKey){ --high; } a[low] = a[high];/// while (low < high && a[low] <= pKey){ ++low; } a[high] = a[low];// } a[low] = pKey; return low; //此时low == high } //快排 void qSort(int[] a, int low, int high){ if (low < high){ int p = position(a, low, high); qSort(a, low, p-1); qSort(a, p+1, high); } } //插入排序 void insertSort(int[] a){ for (int i = 1; i < a.length; ++i){ if (a[i] < a[i-1]){ int temp = a[i]; a[i] = a[i-1]; int j = i-2; /// for (; j >=0 && a[j] > temp; --j){ a[j+1] = a[j]; num++; } a[j+1] = temp; num += 3; } } System.out.println("插入排序" + num); } }