Art of Computer Programming Volume 4: Fascicle 3มีสิ่งเหล่านี้มากมายที่อาจเหมาะสมกับสถานการณ์ของคุณได้ดีกว่าที่ฉันอธิบาย
รหัสสีเทา
ปัญหาที่คุณจะเจอคือหน่วยความจำแน่นอนและรวดเร็วคุณจะมีปัญหา 20 องค์ประกอบในชุดของคุณ - 20 C 3 = 1140 และถ้าคุณต้องการวนซ้ำชุดที่ดีที่สุดคือการใช้สีเทาแก้ไข อัลกอริธึมรหัสดังนั้นคุณไม่ได้เก็บมันไว้ในหน่วยความจำ สิ่งเหล่านี้สร้างชุดค่าผสมถัดไปจากก่อนหน้านี้และหลีกเลี่ยงการทำซ้ำ มีหลายสิ่งสำหรับการใช้งานที่แตกต่างกัน เราต้องการเพิ่มความแตกต่างระหว่างชุดค่าผสมที่ต่อเนื่องหรือไม่ ลด? และอื่น ๆ
เอกสารต้นฉบับบางส่วนที่อธิบายถึงรหัสสีเทา:
- บางเส้นทางแฮมิลตันและอัลกอริทึมการเปลี่ยนแปลงที่น้อยที่สุด
- อัลกอริทึมการสร้างชุดค่าผสม Interchange
นี่คือเอกสารอื่น ๆ ที่ครอบคลุมหัวข้อ:
- การใช้ Eades, Hickey, Read Algorithm การสร้างชุดการแลกเปลี่ยน Interchange ที่อยู่ติดกันอย่างมีประสิทธิภาพ (PDF พร้อมรหัสใน Pascal)
- เครื่องกำเนิดไฟฟ้าแบบผสม
- การสำรวจรหัส Combinatorial Grey (PostScript)
- อัลกอริทึมสำหรับรหัสสีเทา
Chase's Twiddle (อัลกอริทึม)
Phillip J Chase, ` อัลกอริทึม 382: การรวม M จากวัตถุ N '(1970)
อัลกอริทึมใน C ...
ดัชนีชุดค่าผสมในคำสั่งพจนานุกรม (อัลกอริธึม Buckles 515)
นอกจากนี้คุณยังสามารถอ้างอิงชุดค่าผสมตามดัชนีของมัน (ตามลำดับพจนานุกรม) ตระหนักว่าดัชนีควรมีจำนวนการเปลี่ยนแปลงจากขวาไปซ้ายตามดัชนีเราสามารถสร้างสิ่งที่ควรกู้คืนชุดค่าผสม
ดังนั้นเราจึงมีชุด {1,2,3,4,5,6} ... และเราต้องการองค์ประกอบสามอย่าง สมมุติว่า {1,2,3} เราสามารถพูดได้ว่าความแตกต่างระหว่างองค์ประกอบคือหนึ่งและเป็นลำดับและน้อยที่สุด {1,2,4} มีการเปลี่ยนแปลงเพียงครั้งเดียวและเป็นจำนวนตามพจนานุกรม 2 จำนวนดังนั้นจำนวนของ 'การเปลี่ยนแปลง' ในสถานที่สุดท้ายที่บัญชีสำหรับการเปลี่ยนแปลงหนึ่งในการสั่งซื้อพจนานุกรม สถานที่ที่สองโดยมีการเปลี่ยนแปลงหนึ่งครั้ง {1,3,4} มีการเปลี่ยนแปลงเพียงครั้งเดียว แต่บัญชีสำหรับการเปลี่ยนแปลงเพิ่มเติมเนื่องจากอยู่ในสถานที่ที่สอง (ตามสัดส่วนของจำนวนองค์ประกอบในชุดต้นฉบับ)
วิธีที่ฉันอธิบายไว้เป็นโครงสร้างที่ดูเหมือนว่าจากการตั้งค่าเป็นดัชนีเราจำเป็นต้องทำย้อนกลับ - ซึ่งเป็นเรื่องที่ยุ่งยากมาก นี่คือวิธีที่Bucklesแก้ไขปัญหา ฉันเขียนC เพื่อคำนวณพวกมันโดยมีการเปลี่ยนแปลงเล็กน้อย - ฉันใช้ดัชนีของเซตแทนที่จะเป็นช่วงตัวเลขเพื่อแสดงชุดดังนั้นเราจึงทำงานตั้งแต่ 0 ... n บันทึก:
- เนื่องจากชุดค่าผสมไม่ได้เรียงลำดับ {1,3,2} = {1,2,3} - เราจึงสั่งให้ชุดคำเหล่านั้นเป็นพจนานุกรม
- วิธีนี้มีนัย 0 เพื่อเริ่มต้นการตั้งค่าสำหรับความแตกต่างแรก
ดัชนีรวมในคำสั่งพจนานุกรม (McCaffrey)
มีวิธีอื่น : แนวคิดของมันง่ายต่อการเข้าใจและโปรแกรม แต่มันไม่มีการเพิ่มประสิทธิภาพของ Buckles โชคดีที่มันไม่ได้สร้างชุดค่าผสมที่ซ้ำกัน:
ชุดที่เพิ่มที่
ตัวอย่างเช่น27 = C(6,4) + C(5,3) + C(2,2) + C(1,1)
. ดังนั้นการรวมกันของคำศัพท์ที่ 27 ของสี่สิ่งคือ: {1,2,5,6} นั่นคือดัชนีของชุดที่คุณต้องการดู ตัวอย่างด้านล่าง (OCaml) ต้องการchoose
ฟังก์ชั่นจากซ้ายไปอ่าน:
(* this will find the [x] combination of a [set] list when taking [k] elements *)
let combination_maccaffery set k x =
(* maximize function -- maximize a that is aCb *)
(* return largest c where c < i and choose(c,i) <= z *)
let rec maximize a b x =
if (choose a b ) <= x then a else maximize (a-1) b x
in
let rec iterate n x i = match i with
| 0 -> []
| i ->
let max = maximize n i x in
max :: iterate n (x - (choose max i)) (i-1)
in
if x < 0 then failwith "errors" else
let idxs = iterate (List.length set) x k in
List.map (List.nth set) (List.sort (-) idxs)
ตัววนซ้ำชุดเล็กและเรียบง่าย
สองอัลกอริทึมต่อไปนี้จัดทำขึ้นเพื่อวัตถุประสงค์ในการสอน พวกเขาใช้ตัววนซ้ำและชุดรวมโฟลเดอร์ (ทั่วไป) พวกมันเร็วที่สุดโดยมีความซับซ้อน O ( n C k ) k
การใช้หน่วยความจำที่ถูกผูกไว้โดย
เราจะเริ่มต้นด้วยตัววนซ้ำซึ่งจะเรียกฟังก์ชั่นที่ผู้ใช้ระบุสำหรับแต่ละชุด
let iter_combs n k f =
let rec iter v s j =
if j = k then f v
else for i = s to n - 1 do iter (i::v) (i+1) (j+1) done in
iter [] 0 0
รุ่นทั่วไปจะเรียกฟังก์ชันที่ผู้ใช้ให้พร้อมกับตัวแปรสถานะโดยเริ่มจากสถานะเริ่มต้น เนื่องจากเราจำเป็นต้องผ่านสถานะระหว่างสถานะต่าง ๆ เราจะไม่ใช้ for-loop แต่ใช้การเรียกซ้ำ
let fold_combs n k f x =
let rec loop i s c x =
if i < n then
loop (i+1) s c @@
let c = i::c and s = s + 1 and i = i + 1 in
if s < k then loop i s c x else f c x
else x in
loop 0 0 [] x