0 交换数组内的值
/**
* 交换数组内的值
* @param a
* @param b
* @param array
*/
public static void swap(int a, int b, int[] array) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
1 冒泡排序
会一直改变原来的数据结构
/**
* 冒泡排序
* a b c d表示数组的位子上的数字,会发现变换
* 第一轮:
* 比较a和b,如果a大于b,那么交换a,b位子上的数字,接着比较b和c
* 如果c大于b,那么不进行交换,接着比较c和d
* 如果c的数字小于b,那么交换b和c位子上的数字,接着比较c和d
* 第二轮:
* 比较b和c ...
* @param arr
*/
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; ++i) {
for (int j = 0; j < arr.length -1 -i; ++i) {
if (arr[j + 1] < arr[j]){
swap(j, j +1, arr);
}
}
}
}
2 快速排序
/**
* 快速排序
* @param arr 需要进行排序的数组
* @param low 需要排序的起始位置,我们一般填写0
* @param high 需要排序的的结束位置,一般我们填写arr.length -1
* 我们以第一数为基数a,先从最右边开始找到小于a的数字,记录下坐标a1
* 接着从左边开始,找到大于a的值,记录下坐标a2,a1和a2的值进行交换
* 再接着从右边刚刚等停止的位置上开始找小于a的位子,记录...
* 最后当两个指针相遇的时候,交换相遇的位置的坐标点与基数的数字,
* 现在基数已经归位,我们需要做的事情就是讲基数左边和右边的数,进行快速排序
*/
public static void quickSort(int[] arr,int low,int high){
int i, j, temp;
if (low > high) {
return;
}
i = low;
j = high;
//temp就是基准位
temp = arr[low];
while (i < j) {
//先看右边,依次往左递减
while (temp <= arr[j] && i < j) {
j--;
}
//再看左边,依次往右递增
while (temp >= arr[i] && i < j) {
i++;
}
//如果满足条件则交换
if (i < j) {
swap(i, j, arr);
}
}
//最后将基准为与i和j相等位置的数字交换
arr[low] = arr[i];
arr[i] = temp;
//递归调用左半数组
quickSort(arr, low, j-1);
//递归调用右半数组
quickSort(arr, j+1, high);
}
3 选择排序
/**
* 选择排序:
* 第一轮循环:假设第一个数a为最小值,比较后面的值的大小
* 记录下比第一个数小的坐标(数为b),后面比较的是b与后面值得大小
* 如果出现了比b小的数c,那么记录坐标,并且将c与后面的数比较大小
* 运行到最后,可以将第一个数与记录下的最小那个数进行交换
* 第二轮循环:假设第二个数为最小值,....
* @param array
*/
public static void selectSort(int[] array) {
for(int i = 0; i < array.length; ++i) {
int index = i;
for(int j = i +1; j < array.length; ++j){
if(array[j] < array[index]){
index = j;
}
}
if(i != index) {
swap(i, index, array);
}
}
}
4 插入排序
/**
* 插入排序
* a b c 表示所处的位置
* 第一步:比较前面两个的数字a和b的大小,将小的放置在前面
* 第二步:比较c与b的大小,小的话进行交换,并且再次比较a的大小,
* 如果大于b,那么就不需要去b比较a的位子
* 第三步: 比较d:....
* @param array
*/
public static void insertSort(int[] array){
for(int i = 1; i < array.length; ++i){
for(int j = i; j > 0; j--){
if(array[j] < array[j - 1]){
swap(j, j - 1, array);
}else{
break;
}
}
}
}
5 Shell排序
/**
* 希尔排序
* 时间复杂度: O(n1.3)
* 空间复杂度:
* 稳定性: 不稳定 如[5,5,3,3]
* 假设我们的数组为[6,4,2,7,3,1,8,5,9]
* 首先将取得增量,增量的来源是数组长度除以2,得到的增量表示4, 2 , 1
* 那么一开始比较的是6/3, 4/1, 2/8, 7/5, 6/9,得到的数组是【3, 1, 2, 5, 6, 4, 8, 7, 9】
* 接着比较的是3/2, 1/5, 2,/6, 5/4, 6/8, 5/7, 8/9 得到的数组为【2, 1 , 3, 4 , 6, 5, 8 , 7 , 9】
* 最后就是两两的相互比较。
* @param arr
*/
public static void shellSort(int[] arr){
// d 表示增量7 3 1
for(int d = arr.length / 2; d > 0; d /= 2) {
for(int i = d; i < arr.length; ++i) {
for(int j = i - d ; j >= 0; j -= d) {
if(arr[j] > arr [j + d]) {
swap(j, j +d , arr);
}
}
}
}
}
6 堆排序
public static void heapSort(int[] array){
//建堆
initHeap(array);
int count = array.length;
while(count > 1) {
int tmp = array[count - 1];
array[count - 1] = array[0];
array[0] = tmp;
count--; //未排序部分又少一个
//调整过程自上而下,参数root=0
adjustHeap(array, count, 0);
}
}
public static void initHeap(int[] array){
//建堆,从最后一个非叶子节点开始,而最后一个非叶子节点的下标为array.length/2-1
for(int root = array.length/2 - 1; root >= 0; root--){
adjustHeap(array, array.length, root);
}
}
public static void adjustHeap(int[] array, int count, int root){
int maxChildIndex;
//待调整子堆的根节点必须是非叶子节点
while(root <= count/2-1) {
//需要在root、letfchild、rightchild中找到最大的值,
//因为最后一个非叶子节点有可能没有右孩子,所以要做出判断。
if(root == count/2 - 1 && count % 2 == 0){
//节点数量为偶数时,最后一个非叶子节点只有左孩子
maxChildIndex = 2 * root + 1;
}else{
int leftChildIndex = 2 * root + 1;
int rightChildIndex = 2 * root + 2;
maxChildIndex = array[leftChildIndex] > array[rightChildIndex] ?
leftChildIndex : rightChildIndex;
}
if(array[root] < array[maxChildIndex]){
Swap.swap(root,maxChildIndex,array);
//*****************这里很重要,继续调整因交换结构改变的子堆
root = maxChildIndex;
}else{
return;
}
}
}