Rコードの最適化例:クイックソート
の編集
http://www.okadajp.org/RWiki/?R%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%9C%80%E9%81%A9%E5%8C%96%E4%BE%8B%EF%BC%9A%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%BD%E3%83%BC%E3%83%88
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
(no template pages)
SIZE(20){COLOR(magenta){Rコードの最適化例:クイックソート}} [[Rコード最適化のコツと実例集]] に戻る~ 「工学のためのデータサイエンス入門」215-216頁の例、再帰的関数の例。このコードもアルゴリズムの説明を忠実にコード化したという意味で教育的ですが、いかんせんこのままでは遅過ぎ、大きな x を扱えません。 # オリジナルコード(注:少し編集。なお本の中の i0 <- sample(1, 1:n) は間違いです) quick <- function(data){ n <- length(data) if (n <= 1) return(data) # 以下二行は例外処理(これは if 文の出番) if (n == 2) {if (data[1] < data[2]) return(data) else return(data[2:1])} i0 <- sample(1:n, 1) s1 <- s2 <- numeric(0) # 最終長さが未定のベクトルを利用(出来れば避けたい) x <- data[-i0] for (i in 1:(n-1)){ # このループが目障り if (x[i] < data[i0]) s1 <- c(s1,x[i]) else s2 <- c(s2,x[i]) } if (length(s1) == 0) return(c(data[i0], quick(s2))) # 以下3行も似たようなことをしていて気になる if (length(s2) == 0) return(c(quick(s1), data[i0])) return(c(quick(s1), data[i0], quick(s2))) } # Chambers によるコード(少し編集)、「データによるプログランミング」森北出版 (2002) 68頁 # ほれぼれする見事なコード(さすが S 言語の開発者!) # 上のコードの for loop をベクトルの添字操作で隠す(高速化のおまけつき) # 条件 length(x) <= 1 を length(x) == 1 にしてはいけません (x が空の可能性あり) # x[x < fence] は x の要素の内で値が fennce 未満のもの全体(numeric(0), i.e. 長さゼロとなる可能性) # x[x == fence] は x の要素の内で値が丁度 fennce のもの全体 # x[x == fence] を 単に fence としては絶対いけません(タイを含む可能性) # x[x > fence] は x の要素の内で値が fence を越えるもの(numeric(0), i.e. 長さゼロとなる可能性) # ベクトルに numeric(0) を連結しても変わらないことを利用して quick() の最後の目障りな三行を一行ですます quicksort <- function (x) { if (length(x) <= 1) return(x) if (length(x) == 2) {if (x[1] <= x[2]) return(x) else return(x[2:1])} fence = sample(x,1) # 添字を使わず x の要素を直接無作為に取り出している return( c(quicksort(x[x < fence]), x[x == fence], quicksort(x[x > fence])) ) } # 最悪ケースで比較 system.time(x <- quick(10000:1)) [1] 5.58 0.02 5.61 0.00 0.00 system.time(x <- quicksort(10000:1)) [1] 0.63 0.00 0.64 0.00 0.00 system.time(x <- sort(100000:1)) # もちろん組み込み関数 sort() を使えば一瞬 [1] 0.01 0.00 0.03 0.00 0.00
タイムスタンプを変更しない
SIZE(20){COLOR(magenta){Rコードの最適化例:クイックソート}} [[Rコード最適化のコツと実例集]] に戻る~ 「工学のためのデータサイエンス入門」215-216頁の例、再帰的関数の例。このコードもアルゴリズムの説明を忠実にコード化したという意味で教育的ですが、いかんせんこのままでは遅過ぎ、大きな x を扱えません。 # オリジナルコード(注:少し編集。なお本の中の i0 <- sample(1, 1:n) は間違いです) quick <- function(data){ n <- length(data) if (n <= 1) return(data) # 以下二行は例外処理(これは if 文の出番) if (n == 2) {if (data[1] < data[2]) return(data) else return(data[2:1])} i0 <- sample(1:n, 1) s1 <- s2 <- numeric(0) # 最終長さが未定のベクトルを利用(出来れば避けたい) x <- data[-i0] for (i in 1:(n-1)){ # このループが目障り if (x[i] < data[i0]) s1 <- c(s1,x[i]) else s2 <- c(s2,x[i]) } if (length(s1) == 0) return(c(data[i0], quick(s2))) # 以下3行も似たようなことをしていて気になる if (length(s2) == 0) return(c(quick(s1), data[i0])) return(c(quick(s1), data[i0], quick(s2))) } # Chambers によるコード(少し編集)、「データによるプログランミング」森北出版 (2002) 68頁 # ほれぼれする見事なコード(さすが S 言語の開発者!) # 上のコードの for loop をベクトルの添字操作で隠す(高速化のおまけつき) # 条件 length(x) <= 1 を length(x) == 1 にしてはいけません (x が空の可能性あり) # x[x < fence] は x の要素の内で値が fennce 未満のもの全体(numeric(0), i.e. 長さゼロとなる可能性) # x[x == fence] は x の要素の内で値が丁度 fennce のもの全体 # x[x == fence] を 単に fence としては絶対いけません(タイを含む可能性) # x[x > fence] は x の要素の内で値が fence を越えるもの(numeric(0), i.e. 長さゼロとなる可能性) # ベクトルに numeric(0) を連結しても変わらないことを利用して quick() の最後の目障りな三行を一行ですます quicksort <- function (x) { if (length(x) <= 1) return(x) if (length(x) == 2) {if (x[1] <= x[2]) return(x) else return(x[2:1])} fence = sample(x,1) # 添字を使わず x の要素を直接無作為に取り出している return( c(quicksort(x[x < fence]), x[x == fence], quicksort(x[x > fence])) ) } # 最悪ケースで比較 system.time(x <- quick(10000:1)) [1] 5.58 0.02 5.61 0.00 0.00 system.time(x <- quicksort(10000:1)) [1] 0.63 0.00 0.64 0.00 0.00 system.time(x <- sort(100000:1)) # もちろん組み込み関数 sort() を使えば一瞬 [1] 0.01 0.00 0.03 0.00 0.00
テキスト整形のルールを表示する