[Javaの]ソートこれらは十分です

開発プロセスのソート操作は、多くの場合、多くの複雑な問題に直面していることが多い順かつ容易をソートすることができます。良いランキングアルゴリズムは、多くの場合、時間と空間多くのリソースを節約することができます。
ソートするレコードの数、異なるソート処理メモリを使用する場合、二つのカテゴリーに分類することが可能に応じて:内部ソート、コンピュータ分類処理においてランダムアクセスメモリに格納されるすべての並べ替えレコードを指し、アウターソート、非常に大規模なソートするレコードの数を示し、1は、ソート処理の訪問で、外部メモリ・アクセス・レコードの必要性をすべてのメモリを置くことはできません。

内部ソート

  • カテゴリは
    、ソートの5つのカテゴリに分類し、計数挿入ソート、交換のソート、選択ソート、マージ:に分けることができる内部ソートの原理に従って分類されています。
    ソートするソート処理に必要なワークロードに応じて分けることができる:単純な順序(時間計算量はO(N ^ 2))、(時間計算をソート方法(時間複雑度(nlogn)度O)度及び基数ソート前進これは、O(D * N)です)。

  • 挿入ソート
    挿入ソート、単純なソート方法で、彼の基本的な操作は、順序付きリストにレコードを挿入し、新しいレコードリストの新しい、整然とした、プラス数を取得することです。

//直接插入排序
void insertSort (int[] a) {  //非递减排序
        int n = a.length;
        if (n < 2) return; //待排序的记录少于两个
        for (int i = 1; i < n; i ++) {  //a[0]为初始有序序列,进行n - 1次插入排序
            int t = a[i];    //待插入元素
            int j = 0;
            for (j = i - 1; j >= 0 && a[j] > a[t]; j --) {   //对于大于待插入元素的的记录右移
                a[j + 1] = a[j];
            }
            a[j + 1] = t;
        }
    }

挿入は、ソート外観は、私たちは二分探索プロセスを使用して挿入位置が挿入ソートに見える進化させることができ見つける場合、レコードの挿入位置を挿入し、この位置に挿入し、達成するために、順序付けられたシーケンスに基づいています - - バイナリ挿入。

//折半插入排序
void bInsertSort( int[] a) {
        int n = a.length;
        if (n < 2) return;
        for (int i = 1; i < n; i ++) {
            int left = 0, right = i - 1;
            while (left <= right) {
                int mid = (left + right) / 2;
                if (a[mid] < a[i]) left = mid + 1;
                else right = mid - 1;
            }
            int t = a[i];
            for (int j = i - 1; j >= right + 1; j --) {
                a[j + 1] = a[j];
            }
            a[right + 1] = t;
        }
    }

バイナリ挿入と挿入されるソートされたリストの比較に記録されたレコードの数を減少させるが、可動要素の数が低減されていない、それは時間の複雑さはO(N ^ 2)であるままです。記録された運動の数を減らすためにも、2ウェイソートアルゴリズムを提案しました。

//2路插入排序
int[] insertSort2(int[] a) {
        int n = a.length;
        if (n < 2) return a;
        int[] b = new int[n];
        b[0] = a[0];
        int first = 0;
        int last = 0;
        for (int i = 1; i < n; i ++) {
            if (a[i] >= b[0]) {
                int j = 0;
                for (j = last; a[i] < b[j]; j --) b[j + 1] = b[j];
                b[j + 1] = a[i];
                last ++;
            } else {
                if (first == 0) {
                    b[n - 1] = a[i];
                    first = n - 1;
                } else {
                    int j = 0;
                    for (j = first; b[j] < a[i]; j ++) b[j - 1] = b[j];
                    b[j - 1] = a[i];
                    first --;
                }
            }
        }
        return b;
    }

ヒルは、ソート、挿入ソートの方法が、はるかに改善された時間効率のクラスに属する増分還元として知らソート。その複雑さと、それは未解決の数学の問題に関連する計算に関連する増分実績の時系列は、より複雑で、計算の方法はありません。
基本的な考え方はそうすることを、後に繰り返し増分順序に従って並べられ、全体のシーケンスは、基本的な順序になり、ヒルサブシーケンスの複数にソートする列全体、その後、各サブシーケンスのための直接配列をソートすることですその後、容易になります直接挿入ソートを使用します。通常、D [K] = 2 ^(選択 T - K + 1)にインクリメント配列として(これは、この配列はO(N ^(3/2))である時間計算に従ってソートすることを認められた 、t)は、ソートの回数です。

//希尔排序
void sellSort(int a[],int[] d) {
        int n = a.length;
        int m = d.length;
        if(n < 2 || m < 1) return;
        for (int i = 0; i < m; i ++) {  //对a进行m趟希尔排序
            insertSort(a,d[i]);
        }
    }
    /*
    * 一趟希尔排序
    * */
    void insertSort (int[] a,int d) {
        int n = a.length;
        for (int i = d; i < n;i ++) {
            if (a[i] < a[i - d]) {
                int t = a[i];
                int j = i - d;
                while (j >= 0 && t < a[j]) {
                    a[j + d] = a[j];
                    j -= d;
                }
                a[j + d] = t;
            }
        }
    }
  • 交換ソート
    バブルソート
    大シンクダウン。
//冒泡排序
    void guLuGuLuSort(int[] a) {
        int n = a.length;
        if (n < 2) return;
        for (int i = 0; i < n - 1; i ++) {
            for (int j = 0; j < n - 1 - i; j ++) {
                if (a[j] > a[j + 1]) {
                    int t = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = t;
                }
            }
        }
    }

クイック(O(N * LGN))

//递归实现
void quickSort(int[] a,int l,int r) {
        if (l >= r) return;
        int i = l,j = r;
        int mid = a[l];
        while (l < r) {
            while (l < r && a[r] >= mid) r --;
            a[l] = a[r];
            while (l < r && a[l] <= mid) l ++;
            a[r] = a[l];
        }
        a[l] = mid;
        quickSort(a,i,l - 1);
        quickSort(a,l + 1,r);
    }
  • 選択ソート

    選択行は
    、最初の位置にn個の要素の最小値が選択されたn個の選択された-要素の最小値を選択して第2の位置に... N - I要素の最小値に私は1位を+。

//简单选择排序
 void selectSort(int[] a) {
        int n = a.length;
        if (n < 2) return;
        for(int i = 0; i < n; i ++) {
            int min = a[i];
            int p = i;
            for (int j = i;j < n; j++) {
                if (a[j] < a[i]) {
                    min = a[j];
                     p = j;
                }
            }
            a[p] = a[i];
            a[i] = min;
        }
    }
  • ソートマージ
    ソートリストに基づいて行った2つの順序付けられたリストの合併に基づいてマージします。私たちは、順序付けられたリストであると考えられて各要素を並べ替えが開始されます、そのような行動は、複数二十から二にマージされることになる二つの要素のリストを命じました。この順序付けられたリストは、次いで、複数の順序付けられたリストを形成するために対で組み合わさ2つの要素は...ので、n個の要素の合成の順序付きリストまで、上の4つの要素を有しています。
    O(N * LGN)、Oの空間的な複雑さの時間複雑度(N)
public void mergeSort (int[] a, int l,int t) {
        if (l == t) return;
        int m = (l + t) / 2;
        mergeSort(a,l,m);
        mergeSort(a,m + 1,t);
        merge(a,l,m,t);
    }
    public void merge (int[] a, int l, int m, int t) {
        int n = a.length;
        int[] b = new int[n];
        int i = l, j = m + 1;
        int k = l;
        while (i <= m && j <= t) {
            if (a[i] <= a[j]) {
                b[k ++] = a[i ++];
            } else {
                b[k ++] = a[j ++];
            }
        }
        while (i <= m) {
            b[k ++] = a[i ++];
        }
        while (j <= t) {
            b[k++] = a[j++];
        }
        i = l;
        while (i <= t) {
            a[i] = b[i ++];
        }
    }
  • 基数ソート
/*
    * 假设待排对象的元素为正整数
    * */
    public void sort(int[] a) {
        if (a.length < 2) return;
        Note head = new Note();
        Note p = head;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < a.length; i ++) {  //将数组转换链表,顺便找一下最大值
            if (a[i] > max) {
                max = a[i];
            }
            Note note = new Note();
            note.data = a[i];
            note.next = null;
            p.next = note;
            p = p.next;
        }
        int i = 1;
        while (max != 0) {   //进行多次分发和收集
            head = FAC(head, i);
            max /= 10;
            i ++;
        }
        p = head.next;
        i = 0;
        while (p != null) {   //放回到数组
            a[i ++] = p.data;
            p = p.next;
        }

    }
    /*
    * 参数l表示关键字的位置,如l = 1则表示个位为此次分发和收集的关键字
    * */
    public Note FAC(Note head,int l) {
        Note[] h = new Note[10];   //十个分发链的头
        Note p = head.next;
        while (p != null) {    //分发
            int k = (p.data / (int)Math.pow(10,l -1)) % 10;
            if (h[k] == null) {
                h[k] = new Note();
            }
            Note q = h[k];
            while (q.next != null) {
                q = q.next;
            }
            q.next = p;
            p = p.next;
            q.next.next = null;
        }
        Note newHead = new Note();
        for (int i = 0; i< 10; i++) {   //合并
            if (h[i] != null) {
                Note q = newHead;
                while (q.next != null) {
                    q = q.next;
                }
                q.next = h[i].next;
            }
        }
        return newHead;
    }
    class Note {
        int data;
        Note next;
    }
公開された57元の記事 ウォン称賛55 ビュー1919

おすすめ

転載: blog.csdn.net/qq_40561126/article/details/104843262
おすすめ