<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在java中物件進行排序,排序的屬性是string,我們只需要實現Comparator介面,然後實現比較的方式。
public class StringSort { public static void main(String[] args) { test1(); } // 方式1: public static void test1(){ JSONObject jsonObject = JSONObject.parseObject("{"result":[{"id":"A1001","text":"程式設計師"}, {"id":"G1003","text":"建築師"}, {"id":"D1005","text":"設計師"}, {"id":"G1009","text":"自由職業"}, {"id":"E2007","text":"學生"}, {"id":"C1009","text":"教師"}, {"id":"A1002","text":"醫生"}, {"id":"B1005","text":"律師"}, {"id":"F2009","text":"架構師"}]}"); List<JSONObject> list = JSONArray.parseArray(jsonObject.getString("result"), JSONObject.class); list.forEach(System.out::println); Collections.sort(list, new Comparator<JSONObject>() { @Override public int compare(JSONObject o1, JSONObject o2) { return o1.getString("id").compareTo(o2.getString("id") ); // 升序排列 // return - o1.getString("id").compareTo(o2.getString("id") ); // 降序排列 } }); System.out.println("--------------排序後--------------------"); list.forEach(System.out::println); } // 方式2: public static void test2(){ JSONObject jsonObject = JSONObject.parseObject("{"result":[{"id":"A1001","text":"程式設計師"}, {"id":"G1003","text":"建築師"}, {"id":"D1005","text":"設計師"}, {"id":"G1009","text":"自由職業"}, {"id":"E2007","text":"學生"}, {"id":"C1009","text":"教師"}, {"id":"A1002","text":"醫生"}, {"id":"B1005","text":"律師"}, {"id":"F2009","text":"架構師"}]}"); List<JSONObject> list = JSONArray.parseArray(jsonObject.getString("result"), JSONObject.class); list.forEach(System.out::println); Collections.sort(list, (o1, o2) -> { // return o1.getString("id").compareTo(o2.getString("id") ); // 升序排列 return - o1.getString("id").compareTo(o2.getString("id") ); // 降序排列 }); System.out.println("--------------排序後--------------------"); list.forEach(System.out::println); } // 方式3: public static void test3(){ JSONObject jsonObject = JSONObject.parseObject("{"result":[{"id":"A1001","text":"程式設計師"}, {"id":"G1003","text":"建築師"}, {"id":"D1005","text":"設計師"}, {"id":"G1009","text":"自由職業"}, {"id":"E2007","text":"學生"}, {"id":"C1009","text":"教師"}, {"id":"A1002","text":"醫生"}, {"id":"B1005","text":"律師"}, {"id":"F2009","text":"架構師"}]}"); List<JSONObject> list = JSONArray.parseArray(jsonObject.getString("result"), JSONObject.class); list.forEach(System.out::println); Collections.sort(list, Comparator.comparing(o -> o.getString("id"))); System.out.println("--------------排序後--------------------"); list.forEach(System.out::println); } }
對於許多應用,決定順序的鍵都是字串。本篇講述如何利用字串的特殊性質來對其進行高效的排序。
作為熱身,我們先學習一種適用於小整數鍵的簡單排序方法。這種叫做鍵索引計數的方法本身就很實用,同時也是要學習的三種排序演演算法中前兩種的基礎。它其實就桶計數。
現在來情景引入,老師在統計學生的分數時可能會遇到以下資料處理問題。學生被分為若干組,標號為1、2、3、4等。在某些情況下,我們希望將全班同學按組分類。因為組的編號是較小的整數,使用鍵索引計數法來排序時很合適的。假設陣列a[]中的每個元素都儲存了一個名字和一個組號,其中組號在0到R-1之間,程式碼a[i].key()會返回指定學生的組號。四個步驟見程式碼
int N = a.length; int R = 256; //R為字元基數 String[] aux = new String[N]; int[] count = new int[R + 1]; //計算出現頻率 for (int i = 0; i < N; i++) count[a[i].key() + 1]++; //將頻率轉換為索引 for (int r = 0; r < R; r++) count[r + 1] += count[r]; //將元素分類 for (int i = 0; i < N; i++) aux[count[a[i].key()]++] = a[i]; //回寫 for (int i = 0; i < N; i++) a[i] = aux[i];
命題A:鍵索引計數法排序N個鍵為0到R-1之間的整數的元素需要存取陣列11N+4R+1次
如果字串的長度均為W,那就從右向左以每個位置的字元作為鍵,用鍵索引計數法將字串排序W遍。
命題B:低位優先的字串排序演演算法能夠穩定地將定長字串排序
class LSD{ // Least-Significant-Digit First //低位優先的字串排序(基數排序) public static void sort(String[] a, int W) { //通過前W個字元將a[]排序 int N = a.length; int R = 256; //基數 String[] aux = new String[N]; //輔助陣列 for(int d = W - 1; d >= 0; d--) { //根據第d個字元用鍵索引計數法排序 int[] count = new int[R + 1]; //計算出現頻率 for (int i = 0; i < N; i++) count[a[i].charAt(d) + 1]++; //將頻率轉換為索引 for (int r = 0; r < R; r++) count[r + 1] += count[r]; //將元素分類 for (int i = 0; i < N; i++) aux[count[a[i].charAt(d)]++] = a[i]; //回寫 for (int i = 0; i < N; i++) a[i] = aux[i]; } } }
在許多字串排序的應用中,鍵的長度可能互不相同。改進後的低位優先的字串排序是可以適應這些情況的。下來講解兩種處理變長鍵排序的演演算法
首先用鍵索引計數法將所有字串按照首字母排序,然後(遞迴地)再將每個首字母所對應的子陣列排序(忽略首字母,因為每一類中的所有首字母都是相同的)。和快速排序一樣,高位優先的字串排序會將陣列切分為能夠獨立排序的子陣列來完成排序任務,但它的切分會為每個首字母得到一個子陣列,而不是像快速排序中那樣產生固定的兩個或者三個切分。
在高位優先的字串排序演演算法中,要特別注意到達字串末尾的情況。在排序中,合理的做法是將所有字元都已被檢查過的字串所在的子陣列排在所有子陣列的前面,這樣就不需要遞迴地將該子陣列排序。為了簡化這兩步計算,我們使用了一個接受兩個引數的私有方法charAt()來將字串中字元索引轉化為陣列索引,當指定的位置超過了字串末尾時該方法返回-1,。然後將所有返回值加1,得到一個非負的int值並用它作為count[]的索引。這種轉換意味著字串中的每個字元都可能產生R+1種不同的值:0表示字串的結尾,1表示字串的第一個字元,2表示字串的第二個字元,等等。因為建索引計數法本來就需要一個額外的位置,所以使用程式碼int count[] = new int[R + 2]
class MSD{ //高位優先的字串排序 private static int R = 256; //基數 private static final int M = 15; //小陣列的切換閾值 private static String[] aux; //陣列分類的輔助陣列 private static int charAt(String s, int d) { if(d < s.length()) { return s.charAt(d); }else { return -1; } } public static void sort(String[] a) { int N = a.length; aux = new String[N]; sort(a, 0, N - 1, 0); } private static void sortInsert(String[] a, int lo, int hi) { //小型陣列進行插入排序 for (int i = lo + 1; i <= hi; i++) { for(int j = i; j > lo && a[j].compareTo(a[j - 1]) < 0; j--) { String tmp = a[j]; a[j] = a[j - 1]; a[j - 1] = tmp; } } } private static void sort(String[] a, int lo, int hi, int d) { //以第d個字元為鍵將a[lo]至a[hi]排序 if(hi <= lo + M) { sortInsert(a, lo, hi); return; } int [] count = new int[R + 2]; //計算頻率 for(int i = lo; i <= hi; i++) { count[charAt(a[i], d) + 2]++; } for(int r = 0; r < R + 1; r++) { //將頻率轉換為索引 count[r + 1] += count[r]; } for(int i = lo; i <= hi; i++) { //資料分類 aux[count[charAt(a[i], d) + 1]++] = a[i]; } for(int i = lo; i <= hi; i++) { //回寫 a[i] = aux[i - lo]; } //遞迴的以每個字元為鍵進行排序 for(int r = 0; r <R; r++) { sort(a, lo + count[r], lo + count[r + 1] - 1, d + 1); } } }
我們也可以根據高位優先的字串排序演演算法改進快速排序,根據鍵的首字母進行三向切分,僅在中間子陣列的下一個字元(因為鍵得出首字母都與切分字母相同)繼續遞迴排序。這個演演算法的實現並不困難,參考往期排序演演算法中的三向切分快排即可。
儘管排序的方式有所不同,但三向字串快速排序根據的仍然是鍵的首字母並使用遞迴的方法將其餘部分排序。對於字串的排序,這個方法比普通的快速排序和高位優先的字串排序更友好。實際上,它就是兩種演演算法的結合。
三向字串快速排序只將陣列切分為三部分,因此當相應的高位優先的字串排序產生的非空切分較多時,它需要移動的資料量就會變大,因此它需要進行一系列的三向切分才能夠取得多向切分的效果。但是,高位優先的字串排序可能會建立大量(空)子陣列,而三向字串快速排序的切分總是隻有三個。因此三向字串快速排序能夠很好地處理等值鍵、有較長公共字首的鍵、取值範圍較小的鍵和小陣列-----所有高位優先的字串排序演演算法不擅長的各種情況。
class Quick3string{ //三向字串快速排序 private static int charAt(String s, int d) { if(d < s.length()) { return s.charAt(d); } return -1; } public static void sort(String[] a) { sort(a, 0, a.length - 1, 0); } private static void sort(String[] a, int lo, int hi, int d) { if(hi <= lo) { return; } int lt = lo, gt = hi, i = lo + 1; int v = charAt(a[lo], d); while(i <= gt) { int t = charAt(a[i], d); if(t < v) { exch(a, lt++, i++); }else if(t > v) { exch(a, i, gt--); }else { i++; } } //a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi] sort(a, lo, lt - 1, d); if(v >= 0) { sort(a, lt, gt, d + 1); } sort(a, gt + 1, hi, d); } private static void exch(String[] a, int i, int j) { String t = new String(a[i]); a[i] = a[j]; a[j] = t; } }
在將字串陣列a[]排序時,根據它們的首字母進行三向切分,然後(遞迴地)將得到的三個子陣列排序:一個含有所以首字母小於切分字元的字串子陣列,一個含有所以首字母等於切分字串的子陣列(排序時忽略它們的首字母),一個含有所有首字母大於切分字元的字串的子陣列。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45