算法(Java)

一、排序

1.简单选择排序(O(n*n))

【思路】找出数组中最小的元素,将其与第一个元素交换位置,然后再在剩下的元素中找出最小的元素,并与数组的第二个元素交换位置。
【特点】

原地排序,不稳定。
运行时间和输入无关。一个已经有序的数组和一个元素随机排列的数组所用的时间一样。
移动数据最少。交换次数和数组大小是线性关系,每次交换都有一个元素位于正确的位置。

import java.util.Arrays;
public class SelectSort {
    /**
     * 简单选择排序
     * @param a
     */
    public static void sort(int[] a) {
        for(int i =0;i<a.length;i++) {
            int minIndex = i;
            for(int j=i+1;j<a.length;j++) {
                if(a[minIndex]>a[j]) {
                    minIndex = j;
                }
            }
            if(a[i]>a[minIndex]) {
                int temp = a[i];
                a[i] = a[minIndex];
                a[minIndex] = temp;
            }
            System.out.println("第"+(i+1)+"次:"+Arrays.toString(a));
        }
    }
    public static void main(String[] args) {
        int[] a = {9,8,7,5,4,2,1};
        System.out.println("排序前:"+Arrays.toString(a));
        sort(a);
    }
}
输出:
排序前:[9, 8, 7, 5, 4, 2, 1]
第1次:[1, 8, 7, 5, 4, 2, 9]
第2次:[1, 2, 7, 5, 4, 8, 9]
第3次:[1, 2, 4, 5, 7, 8, 9]
第4次:[1, 2, 4, 5, 7, 8, 9]
第5次:[1, 2, 4, 5, 7, 8, 9]
第6次:[1, 2, 4, 5, 7, 8, 9]
第7次:[1, 2, 4, 5, 7, 8, 9]

2.插入排序(O(n*n))

【特点】

原地排序,稳定。
插入排序所需的时间与输入的元素的初始顺序有关。

import java.util.Arrays;
public class InsertSort {
    /**
     * 插入排序
     * @param a
     */
    public static void sort(int[] a) {
        for(int i = 1;i<a.length;i++) {
            for(int j=0;j<i;j++) {
                if(a[j]>a[i]) {
                    int temp = a[i];
                    for(int k = i;k>0;k--) {
                        exch(a,k,k-1);
                    }
                    a[j] = temp;
                    break;
                }
            }
            System.out.println("第"+(i)+"次:"+Arrays.toString(a));
        }
    }
    public static void  exch(int[]a ,int i,int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    public static void main(String[] args) {
        int[] a = {9,8,7,5,4,2,2,1};
        System.out.println("排序前:"+Arrays.toString(a));
        sort(a);
    }
}

输出:
排序前:[9, 8, 7, 5, 4, 2, 1]
第1次:[8, 9, 7, 5, 4, 2, 1]
第2次:[7, 8, 9, 5, 4, 2, 1]
第3次:[5, 7, 8, 9, 4, 2, 1]
第4次:[4, 5, 7, 8, 9, 2, 1]
第5次:[2, 4, 5, 7, 8, 9, 1]
第6次:[1, 2, 4, 5, 7, 8, 9]

3.冒泡排序(O(n*n))

【思路】遍历数组,若相邻的两个元素大小顺序不对,交换这两个元素的位置。
【特点】

稳定。
每次冒泡,会有一个数字位于正确的位置。

import java.util.Arrays;
public class BubbleSort {
    /**
     * 冒泡排序
     * @param a
     */
    public static void sort(int[] a) {//大数从数组后面冒出
        for(int i = a.length-1;i>0;i--) {
            for(int j = 0;j<i;j++) {
                if(a[j]>a[j+1]) {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
            System.out.println("第"+(a.length-i)+"次:"+Arrays.toString(a));
        }
    }
public static void sort1(int[] a) {//小数从数组前面冒出
        for(int i = 0;i<a.length;i++) {
            for(int j = a.length-1;j>i;j--) {
                if(a[j]<a[j-1]) {
                    int temp = a[j];
                    a[j] = a[j-1];
                    a[j-1] = temp;
                }
            }
            System.out.println("第"+(i+1)+"次:"+Arrays.toString(a));
        }
    }
    public static void main(String[] args) {
        int[] a = {9,8,7,5,4,2,2,1};
        System.out.println("排序前:"+Arrays.toString(a));
        sort(a);
    }
}
输出:
排序前:[9, 8, 7, 5, 4, 2, 2, 1]
第1次:[8, 7, 5, 4, 2, 2, 1, 9]
第2次:[7, 5, 4, 2, 2, 1, 8, 9]
第3次:[5, 4, 2, 2, 1, 7, 8, 9]
第4次:[4, 2, 2, 1, 5, 7, 8, 9]
第5次:[2, 2, 1, 4, 5, 7, 8, 9]
第6次:[2, 1, 2, 4, 5, 7, 8, 9]
第7次:[1, 2, 2, 4, 5, 7, 8, 9]

4.希尔排序

【特点】

不稳定。

package com.paixu;
import java.util.Arrays;
public class ShellSort {
    /**
     * 希尔排序
     * @param a
     */
    public static void sort(int[] a) {
        int h = 1;
        int l = a.length;
        while(h<l/3)
            h = h*3+1;
        while(h>=1) {
            for(int i=h;i<l;i++) {
                for(int j=i;j>=h;j--) {
                    if(a[j]<a[j-h]) {
                        int temp = a[j];
                        a[j] = a[j-h];
                        a[j-h] = temp;
                    }
                }
            }
            System.out.println("h="+(h)+":"+Arrays.toString(a));
            h = h/3;
        }
    }
    public static void main(String[] args) {
        int[] a = {9,8,7,5,4,2,2,1};
        System.out.println("排序前:"+Arrays.toString(a));
        sort(a);
    }
}
输出:
排序前:[9, 8, 7, 5, 4, 2, 2, 1]
h=4:[4, 2, 2, 1, 9, 8, 7, 5]
h=1:[1, 2, 2, 4, 5, 7, 8, 9]

5.归并(Merge)排序(N*logN)

需要额外的空间,稳定。

【】自顶向下和自底向上

6.快速排序(N*logN)

分治,将一个数组分成两个子数组,将其独立排序。
【思想】以数组第一个元素(key)对元素进行拆分,设置左右指针,分别从左边找到第一个大于key的元素下表,从右边找出第一个大于key的元素下表,交换其位置,最后将key插入到其位置。然后修改key。

归并排序数组是等分的,快排,切分的位置取决于数组的内容。

【特点】
  • 不稳定。
  • 每次切分就有一个元素处在正确的位置上。
import java.util.Arrays;
public class QuickSort {
    /**
     * 快排
     * @param args
     */

    public static void main(String[] args) {  
        int[] a = {30,25,24,31,28,46,20,40};  
        System.out.println(Arrays.toString(a));  
        quickSort(a);  
        System.out.println(Arrays.toString(a));  
    }  
    public static void quickSort(int[] a) {  
        if(a.length>0) {  
            quickSort(a, 0 , a.length-1);  
        }  
    }  
    public static void quickSort(int[] a,int low,int high) {
        if(low>high)//跳出递归
            return;
        int key = a[low];
        int i = low;
        int j = high;
        int temp = i;
        while(i<j) {
            while(i<j&&a[j] > key) {
                j--;                
            }
            a[i] = a[j];
            temp = i;
            while(i<j&&a[i] <= key) {
                //必须等于且i<j
                i++;
            }
            a[j] = a[i];
            temp = j;
        }
        a[temp] =key;
        System.out.println(Arrays.toString(a));
        quickSort(a,low,i-1);//key左边快排
        quickSort(a,i+1,high);//key右边快排
    }
    
}
输出:
[30, 25, 24, 31, 28, 46, 20, 40]
[20, 25, 24, 28, 30, 46, 31, 40]
[20, 25, 24, 28, 30, 46, 31, 40]
[20, 24, 25, 28, 30, 46, 31, 40]
[20, 24, 25, 28, 30, 46, 31, 40]
[20, 24, 25, 28, 30, 46, 31, 40]
[20, 24, 25, 28, 30, 40, 31, 46]
[20, 24, 25, 28, 30, 31, 40, 46]
[20, 24, 25, 28, 30, 31, 40, 46]
[20, 24, 25, 28, 30, 31, 40, 46]

堆排序(完全二叉树,可以用数组实现而不需要指针)

不稳定。

  • 大根堆:父节点都大于等于它的两个儿子结点。
  • 小根堆:父节点都小于等于它的两个儿子结点。
    int a[];
    int n = 0;// 数组下标0不使用
    public Duipaixu(int maxN){
        a = new int[maxN+1]; 
    }
    public void exch(int i,int j) {
        int k = a[i];
        a[i] = a[j];
        a[j] = k;
    }
    public void insert(int k) {
        a[++n] = k;
        swim(n);
    }
    public void del(int index) {//k是数组下表
        exch(index,n--);
        sink(index);
    }
    public boolean compare(int i,int j) {
        if(a[i]>a[j])
            return false;
        else return true;
    }
    public void swim(int k){//上浮
        while(k>1&&compare(k/2,k)) {
            exch(k/2,k);
            k = k/2;
        }
    }
    public void sink(int k) {//下沉
        while(2*k<n) {
            int j = 2*k;
            if(j<n&&compare(j,j+1)) {
                j++;
            }
            exch(k,j);
            k = j;
        }
    }
    public void print() {// 输出
        int hang = 2;
        for(int i = 1;i<=n;i++) {
            System.out.print(a[i]+" ");
            if(i == hang-1) {
                hang = hang*2;
                System.out.println();
            }
        }
    }
}

二、查找

1.二分查找(时间复杂度O(logN))

        int l0 = 0; 
        int ln = arr.length-1;
        while (l0<=ln) {
            int mid = l0+(ln-l0)/2;
            System.out.println(l0+"  "+mid+" "+ln);
            if(arr[mid] > key) {
                ln = mid-1;
            }
            else if (arr[mid] < key) {
                l0 = mid+1;
            }
            else return mid;
        }
        return -1;
    }
public static int BinarySearch(int[] a,int key,int low,int high) {// 递归实现
        int mid = low+(high-low)/2;
        if(a[mid]==key) {
            return mid;
        }
        else if(a[mid]>key) {
            return DiguiBinary(a,key,low,mid-1);
        }
        else return DiguiBinary(a,key,mid+1,high);
    }

2.二叉排序树(时间复杂度O(logN))


3.B树

B树是一种多路搜索树,主要用在文件系统和数据库系统,文件系统和数据库主要存储在磁盘,B树就是为了降低磁盘I/O次数。
二叉排序树深度是logN,所以时间复杂度是O(logN),要降低复杂度,就要降低树的深度。它是一种平衡多路查找树。


B+树(查找两个值之间的多个元素时)

索引都是排好序的。

  • 只有最底层的节点(叶子节点)才保存信息。
  • 其它节点(非叶子结点)只是在搜索中用来指引到正确节点的。
  • 结点个数多了一倍
  • 叶子结点跟后续叶子结点是连接的,
  • 插入和删除操作的时间复杂度是 O(log(N)) 。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容

  • 一些概念 数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算,而且确保经过这...
    Winterfell_Z阅读 5,637评论 0 13
  • 概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的...
    Luc_阅读 2,253评论 0 35
  • 课程介绍 先修课:概率统计,程序设计实习,集合论与图论 后续课:算法分析与设计,编译原理,操作系统,数据库概论,人...
    ShellyWhen阅读 2,237评论 0 3
  • 第一章 绪论 什么是数据结构? 数据结构的定义:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 第二章...
    SeanCheney阅读 5,726评论 0 19
  • 《牡丹亭》中,<游园>一段六支曲子,是如何刻画杜丽娘心理变化的? 这六支曲子,我们一起来看看吧。 第一支【绕池游】...
    若愚2021阅读 1,889评论 0 0