slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
???????? ??? ????????????????? PowerPoint Presentation
Download Presentation
???????? ??? ?????????????????

Loading in 2 Seconds...

play fullscreen
1 / 92

???????? ??? ????????????????? - PowerPoint PPT Presentation


  • 139 Views
  • Uploaded on

อาร์เรย์ และ การจัดเรียงข้อมูล. a. 7. 6. 4. 5. 8. 9. a คือตัวแปรที่เป็นชื่อของอาร์เรย์นี้ ในภาษาจาวานั้น อาร์เรย์เป็น object ชนิดหนึ่ง เพราะฉะนั้น a ในที่นี้คือ object reference นั่นเอง พูดง่ายๆคือ a เป็นตัวลูกศรที่จะชี้ไปยังส่วนที่เก็บค่าต่างๆของอาร์เรย์นั่นเอง.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '???????? ??? ?????????????????' - hazina


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

อาร์เรย์ และ การจัดเรียงข้อมูล

a

7

6

4

5

8

9

a คือตัวแปรที่เป็นชื่อของอาร์เรย์นี้

ในภาษาจาวานั้นอาร์เรย์เป็น object ชนิดหนึ่งเพราะฉะนั้น a ในที่นี้คือ object reference นั่นเองพูดง่ายๆคือ a เป็นตัวลูกศรที่จะชี้ไปยังส่วนที่เก็บค่าต่างๆของอาร์เรย์นั่นเอง

อ.ดร.วิษณุ โคตรจรัส

index
Index ของอาร์เรย์
  • เราใช้ a[index] อ่านตำแหน่งต่างๆของอาร์เรย์จากรูปในหน้าที่แล้ว
    • a[0] จะหมายถึง 7 และ a[1] จะหมายถึง 6
  • ค่า index จะเริ่มต้นที่ 0 (สำหรับภาษาจาวา)
  • ทุกค่า index จะต้องเป็นจำนวนเต็มเสมอรวมทั้งเป็น expression ที่คำนวณแล้วได้จำนวนเต็มก็ได้
    • เช่นถ้า b=2 กับ c=3 แล้วa[b+c] ถือว่าเป็นการกล่าวถึงสมาชิกของอาร์เรย์ได้ถูกต้องตัว a[b+c] นี้ก็สามารถถูกนำไปใช้ได้เหมือนตัวแปรธรรมดาเช่น a[b+c] += 5;

อ.ดร.วิษณุ โคตรจรัส

slide3
ขนาดของอาร์เรย์
  • ในจาวาเองทุกๆอาร์เรย์จะมีตัวแปร length
    • ที่จะถูกตั้งค่าไว้โดยอัตโนมัติตอนที่อาร์เรย์ถูกสร้างขึ้น
    • เราสามารถใช้ a.length หาขนาดของอาร์เรย์ a ได้ทันที

อ.ดร.วิษณุ โคตรจรัส

slide4
การสร้างอาร์เรย์ใน Java
  • ประกอบด้วยสองขั้นตอนใหญ่ๆคือ
    • Array Declaration: คือการนิยามตัวแปรอาร์เรย์ขึ้นมา
    • Array Allocation: คือการสร้างออบเจ็กต์ที่เป็นอาร์เรย์ขึ้นมาจริงๆแล้วใช้ assignment operator ทำให้ตัวแปรในข้อ 1 ชี้มายังตัวออบเจ็กต์นี้

อ.ดร.วิษณุ โคตรจรัส

slide5
การสร้างอาร์เรย์ใน Java (ต่อ)

int x[]; //Declaration –นี่คือการนิยามตัวแปร x ให้เป็นอาร์เรย์ของ

//จำนวนเต็มแต่ยังไม่มีออบเจ็กต์จริงๆเกิดขึ้น

x=new int[5]; //Allocation –นี่คือการสร้างอาร์เรย์ออบเจ็กต์ขนาด5 ช่อง

// เมื่อทำแล้วจะได้อาร์เรย์ที่มีค่าในแต่ละช่องเป็นค่า default

//ของข้อมูลชนิดนั้นในที่นี้จะมี 0 อยู่ทั้ง 5 ช่องจากนั้นเอา

// x ชี้ไปที่ตัวอาร์เรย์

จะเห็นว่าต้องมีการกำหนดจำนวนช่องให้แน่นอนตอนสร้าง

อ.ดร.วิษณุ โคตรจรัส

java initializer list
การสร้างอาร์เรย์ใน Java โดยใช้ initializer list
  • เราสามารถสร้างอาร์เรย์ x ของจำนวนเต็ม 1 2 และ 3 ได้ด้วย

int x[] = {1,2,3};

โดย {1,2,3}คือ initializer list นั่นเอง

อ.ดร.วิษณุ โคตรจรัส

object

null

null

null

การสร้างอาร์เรย์ของ Object
  • ถ้ามีออบเจ็กต์ type MyObject เราก็สร้างอาร์เรย์ขนาด 3 ช่องของมันได้

MyObject a[] = new MyObject[3];

  • โดยตัวอาร์เรย์ที่ถูกสร้างจะมีค่าเริ่มต้นของสมาชิกเป็นnull

a

อ.ดร.วิษณุ โคตรจรัส

slide8

0

0

0

0

0

0

0

0

0

อาร์เรย์ของอาร์เรย์
  • int x[][] = new int[3][3];

a

อ.ดร.วิษณุ โคตรจรัส

initializer list

x

5

6

1

2

3

4

อาร์เรย์ของอาร์เรย์ (ใช้ initializer list)
  • int x[] = {{1,2},{3,4},{5,6}};

อ.ดร.วิษณุ โคตรจรัส

matrix
Matrix
  • สำหรับอาร์เรย์ 2 ชั้นนั้นเราสามารถดูให้เป็นเมตริกซ์ได้โดยให้index ตัวแรกแทนแถวและตัวที่ 2 แทนหลัก
  • อาร์เรย์จากหน้าที่แล้วจึงสามารถมองได้เป็น

อ.ดร.วิษณุ โคตรจรัส

initialize
การเว้นไม่ initialize ค่าในตอนสร้างอาร์เรย์

int y [][] = new int [2][];

  • ตัว index ตัวหลังนั้นเราเว้นไว้ได้
  • อาร์เรย์ในชั้นที่ 2 ก็จะเป็น null ไปก่อน
  • แต่อย่างไรก็ตามต้องมีการ initialize อาร์เรย์ชั้นนี้ให้เรียบร้อยก่อนที่จะมีการนำสมาชิกภายในไปใช้
  • ในตัวอย่างนี้เราอาจทำการ initialize อาร์เรย์ย่อยได้ดังนี้

y[0] = new int[2];

y[1] = new int[3];

  • จะเห็นได้ว่าอาร์เรย์ย่อยไม่จำเป็นต้องมีขนาดเท่ากัน

อ.ดร.วิษณุ โคตรจรัส

bubble sort

5

2

4

3

1

Bubble Sort
  • เปรียบเทียบสองจำนวนแรกในอาร์เรย์ สลับที่สองจำนวนนี้ถ้าจำนวนขวามีค่าน้อยกว่าจำนวนซ้าย
  • ต่อจากนั้นก็มาเปรียบเทียบตัวเลขคู่ถัดมาในอาร์เรย์นั้น(ซึ่งตัวแรกอาจเคยถูกสลับที่มาแล้ว) แล้วทำการสลับที่ในกรณีเดียวกัน

2

5

4

3

1

  • ทำไปเรื่อยๆจนถึงคู่สุดท้าย แล้วก็กลับมาเปรียบเทียบคู่แรกใหม่ ทำไปเรื่อยๆ

อ.ดร.วิษณุ โคตรจรัส

running time bubble sort
Running time ของ Bubble Sort
  • การสลับที่ต้องมีจำนวนครั้งที่เพียงพอที่จะเคลื่อนค่าที่
    • มากที่สุดจากช่องซ้ายสุดของอาร์เรย์ไปยังช่องขวาสุด
    • น้อยที่สุดจากช่องขวาสุดของอาร์เรย์ไปยังช่องซ้ายสุด

n จำนวน

5

2

4

3

1

Big O = O(n2)

  • n-1 ครั้งแรกจะเพียงพอทำให้ค่าที่อยู่ช่องซ้ายสุด (5) เคลื่อนไปยังช่องขวาสุดได้แต่ข้อมูลในช่องขวาสุด (1) นั้นจะเลื่อนมาได้เพียงหนึ่งช่องเท่านั้น
  • ดังนั้นต้องทำซ้ำอย่างนี้ไปอีก n-1 รอบ

อ.ดร.วิษณุ โคตรจรัส

slide14
1: public static void bubblesort(int[] array){

2: for (int pass = 1; pass<=array.length-1; pass++)

3: for(int element=0; element<= array.length –2; element++)

4: if(array[element] > array[element+1])

5: swap(array, element, element +1);

6: }

เปรียบเทียบและสลับ 1 คู่

}

1: public static void swap(int[] array, int a, int b){

2: int temp = array[a];

3: array[a]= array[b];

4: array[b]= temp;

5:}

อ.ดร.วิษณุ โคตรจรัส

worst case bubble sort

4

4

3

4

3

4

5

3

3

4

3

2

2

3

5

4

2

2

3

1

2

4

3

5

1

1

5

1

2

2

2

4

5

5

1

1

5

1

1

5

Worst case ของ Bubble Sort (อาร์เรย์เรียงจากมากไปน้อย)

ไม่ต้องสลับ

ลูปแรกมีการเปรียบเทียบn-1ครั้งและมีการสลับที่n-1ครั้ง

ลูปที่2 มีการเปรียบเทียบn-1ครั้งเหมือนเดิมแต่มีการสลับที่แค่n-2 ครั้ง

อ.ดร.วิษณุ โคตรจรัส

worst case bubble sort1
Worst case ของ Bubble Sort (ต่อ)
  • มีการเปรียบเทียบข้อมูลn-1 ครั้งในแต่ละลูปและโค้ดเรามีทั้งหมดn-1 ลูป
    • เพราะฉะนั้นจะมีการเปรียบเทียบข้อมูลในอาร์เรย์(n-1)2ครั้ง
  • มีการสลับที่ของข้อมูลในอาร์เรย์ (n-1) + (n-2) + (n-3) +…+ 1 = n(n-1)/2ครั้ง
  • bubble sort (worst case)

= (n-1)2 + n(n-1)/2 * unit time ของการสลับที่

= (n-1)2 + n(n-1)/2 * 3

= (5n2– 7n +2) /2

อ.ดร.วิษณุ โคตรจรัส

selection sort
Selection Sort
  • เก็บค่า index ของสมาชิกตัวแรกของอาร์เรย์ a เอาไว้ในตัวแปร maxindex
  • ตรวจสอบสมาชิกของอาร์เรย์ที่ละตัวตามลำดับถ้าเจอตัวที่มีค่ามากกว่า a[maxindex] ก็ให้เปลี่ยนค่า maxindex ให้เก็บ index ค่าใหม่ตรวจจนหมดอาร์เรย์
  • สลับที่สมาชิกตัวสุดท้ายของอาร์เรย์กับ a[maxindex] (ถ้าสองตัวนี้ไม่ใช่ตัวเดียวกัน) เพื่อให้ค่าที่มากที่สุดไปอยู่ขวาสุด
  • ทำข้อ 1 – 3 ใหม่กับสมาชิก n-1 ตัวที่เหลือแล้วทำต่อไปโดยสมาชิกจะลดลงเรื่อยๆ

อ.ดร.วิษณุ โคตรจรัส

selection sort1

maxindex =0

maxindex ยังคงเป็น 0 ตอนนี้ก็สลับที่a[maxindex] กับa[4]

เริ่มใหม่

maxindex =0

maxindex กลายเป็น 1 แล้วสลับที่a[maxindex] กับa[3]

5

2

4

4

3

3

1

1

2

5

ตัวอย่าง Selection Sort

เปรียบเทียบ n-1 ครั้ง สลับที่ 1 ครั้ง

เปรียบเทียบ n-2 ครั้ง สลับที่ 1 ครั้ง

อ.ดร.วิษณุ โคตรจรัส

selection sort code

Big O = O(n2)

Selection Sort (Code)

ลดขนาดอาร์เรย์ลงเรื่อยๆ

public static void selectionSort(int[] a){

int maxindex; //index of the largest value

for(int unsorted= a.length; unsorted > 1; unsorted--){

maxindex = 0;

for(int index= 1; index < unsorted; index++){

if(array[maxindex] < array[index])

maxindex = index;

}

if(a[maxindex] != a[unsorted -1])

swap(array, maxindex, unsorted -1);

}

}

ไล่ตรวจอาร์เรย์ 1 รอบเพื่อ update maxindex

สลับที่ถ้าไม่ใช่ค่าเดียวกัน

อ.ดร.วิษณุ โคตรจรัส

selection sort worst case
Selection Sort (worst case)
  • นับเวลาจากการเปรียบเทียบข้อมูลในอาร์เรย์และการ assign ข้อมูลเข้าหรือออกจากอาร์เรย์เท่านั้น
  • จะเกิดเมื่อมีการสลับที่ทุกรอบการใช้ลูป นั่นคือ ข้อมูลเกือบจะเรียงกัน แต่ตัวที่น้อยที่สุดอยู่ท้ายสุด เช่น 2,3,4,5,1 นับได้ดังนี้
    • การเปรียบเทียบข้อมูลในอาร์เรย์ (n-1) + (n-2) + … + 1 ครั้ง
    • การเปรียบเทียบข้อมูลในอาร์เรย์เพื่อตัดสินการสลับที่ (n-1) ครั้ง
    • การสลับที่สมาชิกของอาร์เรย์ n-1 ครั้ง

รวมได้ (n2 + 7n -8) /2 ซึ่งเร็วกว่า bubble sort เมื่อ n เป็น 3 ขึ้นไป

อ.ดร.วิษณุ โคตรจรัส

insertion sort
Insertion Sort
  • แบ่งอาร์เรย์เป็นข้างซ้ายและขวา ให้ข้างซ้ายเป็นข้างที่ถือว่าจัดเรียงแล้ว (แน่นอนว่าในตอนเริ่มต้องมีจำนวนสมาชิกในข้างนี้แค่ตัวเดียว)
  • ตรวจข้างขวาของอาร์เรย์โดยไล่ตรวจที่ละตัว ถ้าเจอตัวที่มีค่าน้อยกว่าตัวสุดท้ายของข้างซ้าย ให้เอาตัวนั้นไปใส่ในข้างซ้ายให้ถูกที่
  • ทำซ้ำข้อ 1 โดยขยายขนาดของข้างซ้ายเพิ่มขึ้น 1 ตัว ทำไปเรื่อยๆ

อ.ดร.วิษณุ โคตรจรัส

insertion sort1

6

5

5

6

3

3

7

7

4

4

ตัวอย่าง Insertion Sort

ด้านซ้ายนี่ถือว่าเรียงแล้ว

ต้องเอา 5 ไปใส่ข้างหน้า (หรือเลื่อน 6 มาแล้วค่อยเอา 5 ใส่แทน)

เลื่อน 5 กับ 6 อย่างละ 1 ช่อง แล้วเอา 3 ใส่ช่องแรก

อ.ดร.วิษณุ โคตรจรัส

slide23

3

3

5

5

6

6

7

7

4

4

ไม่ต้องเลื่อนเพราะอยู่ถูกที่

เลื่อน 5,6,7 แล้วเอา 4 ใส่ช่องหลัง 3 ก็จะเสร็จ

ตัวอย่าง Insertion Sort (ต่อ)

อ.ดร.วิษณุ โคตรจรัส

slide24

Big O = O(n2)

5

6

3

7

4

ตัวที่จะจับยัดเข้าด้านซ้าย

public static void insertionSort(int[] a){

int index;

for(int numSorted = 1; numSorted < a.length; numSorted++){

int temp = a[numSorted];

for(index = numSorted; index >0; index--){

if(temp< a[index-1]){

a[index] = a[index –1];

} else{

break;

}

}

a[index] = temp;

}

}

ไล่เปรียบเทียบกับ 6 และ 5 ตามลำดับ ทำให้ 6 เลื่อนขวา 1 ช่อง และ 5 ก็เลื่อนขวา 1 ช่อง

พอไม่มีตัวไหนเลื่อนได้ก็ใส่ 3 ลงที่ที่ 5 เคยอยู่

อ.ดร.วิษณุ โคตรจรัส

slide25

Insertion Sort (worst case)

  • Worst case เกิดเมื่อต้องมีการเลื่อนสมาชิกของอาร์เรย์มากที่สุด
    • นั่นคืออาร์เรย์ต้องเรียงจากมากไปน้อย
    • แต่ละรอบ ทุกสมาชิกของข้างซ้ายของอาร์เรย์จะต้องถูกเลื่อนไป 1 ตำแหน่ง

อ.ดร.วิษณุ โคตรจรัส

slide26

Insertion Sort (worst case ต่อ)

  • unit time ของ worst case insertion sort

=(1+2+..+n-1)*2 + n-1

= n(n-1) + n-1

= (n+1)(n-1) = n2–1

เร็วกว่า selection sort เมื่อ n มีค่าไม่เกิน 6 เท่านั้น

อ.ดร.วิษณุ โคตรจรัส

insertion sort2
Insertion Sort (กรณีเฉลี่ย)

ถ้าเราอยู่ที่ลูปนอกสุดลูปที่ i

  • ถ้า a[i] อยู่ในที่ที่ไม่ต้องมีการเลื่อนจะเกิดการเปรียบเทียบ temp< a[index-1] เพียงครั้งเดียวเท่านั้น
  • ถ้า a[i] อยู่ในที่ที่ต้องมีการเลื่อนตำแหน่งจะมีการเปรียบเทียบเกิดขึ้นได้ตั้งแต่หนึ่งครั้งจนถึง i ครั้ง
    • เช่นถ้า i มีค่าเป็น 2 จะต้องมีการเปรียบเทียบ a[2] กับ a[1] (นี่นับเป็นครั้งที่หนึ่ง)
    • และจากนั้นถ้าเกิดการเลื่อน a[1] ไปใส่ a[2] จะต้องเปรียบเทียบค่าเดิมของ a[2] กับ a[0] ด้วย

อ.ดร.วิษณุ โคตรจรัส

slide28

Insertion Sort (กรณีเฉลี่ย ต่อ)

  • ฉะนั้นถ้าเราดูแต่จำนวนครั้งของการเปรียบเทียบจะได้ว่าในลูปที่ i มีจำนวนการเปรียบเทียบโดยเฉลี่ย

ครั้ง

  • ดังนั้นถ้าคิดทุกลูปค่าจำนวนครั้งของการเปรียบเทียบที่เกิดขึ้นจะเป็น

ครั้ง

  • ดังนั้นจึงสรุปได้ว่าค่าเวลาเฉลี่ยจะเข้าใกล้ค่าเวลาของworst case

อ.ดร.วิษณุ โคตรจรัส

merge sort
Merge Sort
  • แบ่งอาร์เรย์เป็นสองส่วนไปจัดเรียงข้อมูลในแต่ละส่วนให้เรียบร้อย
    • (แต่ละอาร์เรย์ก็แบ่งสองส่วนได้อีกทำเป็นrecursion ได้)
  • รวมอาร์เรย์ที่จัดเรียงเรียบร้อยเข้าด้วยกัน

อ.ดร.วิษณุ โคตรจรัส

merge sort 1
การรวมอาร์เรย์ใน merge sort (ขั้นที่ 1)
  • สมมติเราจะ รวมอาร์เรย์a (1,5,8,9) กับb (2,4,6,7)
  • ให้มีcounter อยู่ที่index แรกของอาร์เรย์ทั้งสองแล้วสร้างอาร์เรย์สำหรับเก็บผลการรวมขึ้นมา–ในที่นี้เราเรียกว่าอาร์เรย์ c

b

c

a

1

5

8

9

2

4

6

7

indexB

indexC

indexA

อ.ดร.วิษณุ โคตรจรัส

merge sort 2
การรวมอาร์เรย์ใน merge sort (ขั้นที่ 2)
  • เปรียบเทียบ a[indexA] กับ b[indexB] เอาค่าที่น้อยกว่า ใส่ c[indexC] แล้วเลื่อน counter ของตัวที่น้อยนั้นและของ c เพื่อเตรียมเปรียบเทียบครั้งต่อไป

b

c

a

1

5

8

9

2

4

6

7

1

indexB

indexA

indexC

อ.ดร.วิษณุ โคตรจรัส

merge sort 3
การรวมอาร์เรย์ใน merge sort (ขั้นที่ 3)
  • เปรียบเทียบ a[indexA] กับ b[indexB] แบบนี้ไปเรื่อยๆจนหมดหนึ่งอาร์เรย์ ในที่นี้ b จะหมดก่อน

b

c

a

1

5

8

9

2

4

6

7

1

2

4

5

6

7

indexB

indexC

indexA

  • หลังจากนี้ก็แค่ก็อปปี้ส่วนที่เหลือของ a ใส่ c ให้หมด
  • ก็จะได้อาร์เรย์ผลลัพธ์ที่สมบูรณ์

อ.ดร.วิษณุ โคตรจรัส

worst case
Worst case ของการรวมอาร์เรย์
  • Worst case ของการรวมอาร์เรย์นี้ เกิดเมื่อต้องมีการเปรียบเทียบสมาชิกอาร์เรย์ทั้งสอง(a กับ b) ไปจนถึงสมาชิกตัวสุดท้ายของทั้งคู่
  • ซึ่งจะมีการเปรียบเทียบทั้งหมด n-1 ครั้ง (n คือขนาดของอาร์เรย์ผลลัพธ์) เพราะฉะนั้น เวลาในการทำงานของการรวมอาร์เรย์จึงเป็น O(n)

อ.ดร.วิษณุ โคตรจรัส

slide34
โค้ดของการรวมอาร์เรย์โค้ดของการรวมอาร์เรย์

public static int[] merge(int[] a, int[] b){

int aIndex = 0; int bIndex = 0; int cIndex = 0;

int aLength = a.length; int bLength = b.length;

int cLength = aLength + bLength;

int[] c = new int[cLength];

//ก่อนอื่นเปรียบเทียบ a กับ b แล้วเอาเลขออกใส่ c จนอาร์เรย์ตัวใดตัวหนึ่งหมด

while((aIndex < aLength) && (bIndex < bLength){

if(a[aIndex]<=b[bIndex]){

c[cIndex] = a[aIndex];

aIndex++;

}else{

c[cIndex] = b[bIndex];

bIndex++;

}

cIndex++;

}

มีต่อ

อ.ดร.วิษณุ โคตรจรัส

slide35
โค้ดของการรวมอาร์เรย์(ต่อ)โค้ดของการรวมอาร์เรย์(ต่อ)

//ต่อไปก็ก็อปปี้อาร์เรย์ที่เหลือใส่ c ให้หมด

if(aIndex == aLength){ //ถ้า a ถูกใช้หมดก่อน

while(bIndex<bLength){

c[cIndex] = b[bIndex];

bIndex++;

cIndex++;

}

}else{ //ถ้า b ถูกใช้หมดก่อน

while(aIndex<aLength){

c[cIndex] = a[aIndex];

aIndex++;

cIndex++;

}

}

return c;

}

อ.ดร.วิษณุ โคตรจรัส

slide36
การแบ่งอาร์เรย์เป็นส่วนๆการแบ่งอาร์เรย์เป็นส่วนๆ
  • ไม่ต้องมาจัดเรียงข้อมูลในตอนนี้เลยด้วยซ้ำ เพราะ
    • เมื่อเราแบ่งอาร์เรย์ไปเรื่อยๆ ผลสุดท้ายจะได้อาร์เรย์ที่มีขนาดเพียงหนึ่งมารวมกัน ตอนรวมอาร์เรย์ขนาดหนึ่งเข้าด้วยกันก็จะเป็นการจัดเรียงไปในตัวเลย
    • ฉะนั้น การรวมอาร์เรย์ที่ใหญ่ขึ้นมาก็จะมีการจัดเรียงอยู่แล้วโดยปริยาย

อ.ดร.วิษณุ โคตรจรัส

slide37
โค้ดของการแบ่งอาร์เรย์เป็นส่วนๆโค้ดของการแบ่งอาร์เรย์เป็นส่วนๆ

1: public static int[] mergeSort(int[] unsort, int left, int right){

2: if(left == right){//ถ้าไม่เหลืออะไรให้จัดแล้วต้องตอบเป็นอาร์เรย์ขนาด 1

3: int[] x = new int[1];

4: x[0] = unsort[left];

5: return x;

6: }

7: else if(left<right){//ถ้ายังจัดได้ก็แบ่งอาร์เรย์ต่อไป

8: int center = (left+right)/2;

9: int[] result1 = mergeSort(unsort,left,center);

10: int[] result2 = mergeSort(unsort,center+1,right);

11: return merge(result1,result2);

12: }

13: }

อ.ดร.วิษณุ โคตรจรัส

merge sort1
เวลาในการทำงานของ merge sort
  • ถ้ามีสมาชิกตัวเดียวเราเห็นได้ชัดว่าเวลาที่ใช้นั้นคงที่ (ให้เป็น 1 ได้)
  • ส่วนถ้ามีสมาชิกหลายตัวเวลาที่ใช้จะเท่ากับเวลาที่ทำงานครึ่งซ้ายรวมกับครึ่งขวาแล้วรวมกับเวลาที่ใช้ในการรวมอาร์เรย์ทั้งสองอีกทีหนึ่ง (ซึ่งเป็นO(n))

อ.ดร.วิษณุ โคตรจรัส

merge sort2
เวลาในการทำงานของ merge sort (ต่อ)
  • เอา n หารตลอดเราจะได้

(1)

  • เราเอามาเขียนเป็นชุดของสมการ โดยเปลี่ยนค่า n ไปเรื่อยๆ จะได้สมการชุดในหน้าถัดไป

อ.ดร.วิษณุ โคตรจรัส

merge sort 21
เวลาในการทำงานของ merge sort (ต่อ 2)

(2)

(3)

(x)

อ.ดร.วิษณุ โคตรจรัส

merge sort 31
เวลาในการทำงานของ merge sort (ต่อ 3)
  • เอาสมการตั้งแต่ (1) ถึง (x) มาบวกกัน จะได้
  • จะเห็นว่าmerge sort นั้นมีเวลาเร็วกว่าการจัดเรียงข้อมูลแบบอื่นๆที่กล่าวมา
  • แต่การจัดเรียงข้อมูลด้วยวิธีนี้มีข้อเสียคือต้องใช้พื้นที่ในการสร้างอาร์เรย์ที่เป็นผลรวมของสองอาร์เรย์ย่อย

อ.ดร.วิษณุ โคตรจรัส

quick sort
Quick Sort

1. ถ้าไม่มีสมาชิกในอาร์เรย์หรือมีสมาชิกแค่ตัวเดียวให้ตอบเป็นอาร์เรย์นั้นเลยเพราะถือว่าแบบนี้ข้อมูลจัดเรียงในตัวเองอยู่แล้ว

2. เลือกตัวเลขใดตัวเลขหนึ่งในอาร์เรย์มาให้จำนวนนั้นเป็นจุดหลัก (ต่อไปนี้จะเรียกว่า pivot)

3. ใช้ pivot เป็นหลักเลื่อนสมาชิกทุกตัวที่น้อยกว่า pivot ไปอยู่ด้านซ้ายของ pivot และเลื่อนสมาชิกทุกตัวที่มากกว่า pivot ไปอยู่ด้านขวาของ pivot (ส่วนสมาชิกที่มีค่าเท่ากับpivot ก็แล้วแต่จะจัดการวิธีที่ดีที่สุดน่าจะเป็นการกระจายจำนวนเหล่านี้ไปยังทั้งสองข้างเท่าๆกัน) ขั้นตอนนี้เรียกว่าการ partition

4. ตอนนี้ตัว pivot ก็จะได้อยู่ในที่ที่ถูกต้องเรียบร้อยแล้วที่เราเหลือต้องทำก็คือทำquick sort กับอาร์เรย์ย่อยข้างซ้ายและข้างขวาของ pivot

5. คำตอบคืออาร์เรย์ที่เกิดจากการต่อ quicksort(ด้านซ้าย) กับ pivot กับ quicksort(ด้านขวา)

อ.ดร.วิษณุ โคตรจรัส

quick sort1

3

3

5

1

6

4

1

5

6

4

ภาพหลักการทำ quick sort

เลือกตัวนี้เป็น pivot

ต่อไป แบ่งข้อมูลเป็นสองข้างของ 4

เอาไป quick sort

เอาไป quick sort

เอาผลมาต่อกัน จะได้คำตอบ

อ.ดร.วิษณุ โคตรจรัส

slide44
ขั้นที่ 1: เมื่ออาร์เรย์มีขนาดเล็ก
  • ถ้าไม่มีสมาชิกในอาร์เรย์หรือมีสมาชิกแค่ตัวเดียวให้ตอบเป็นอาร์เรย์นั้นเลยเพราะถือว่าแบบนี้ข้อมูลจัดเรียงในตัวเองอยู่แล้ว
  • แต่เราจะเห็นว่าจริงๆแล้วถ้าอาร์เรย์มีจำนวนสมาชิกน้อย(น้อยกว่า 20) ใช้ insertion sort จะเร็วกว่าซะอีกดังนั้นถ้าอาร์เรย์มีขนาดเล็กเราควรใช้วิธีจัดเรียงแบบอื่นแล้วค่อยเอาคำตอบจากวิธีนั้นมา

อ.ดร.วิษณุ โคตรจรัส

2 pivot
ขั้นที่ 2: การเลือก pivot
  • ห้ามใช้ตัวแรกของอาร์เรย์เป็นpivot เด็ดขาด
    • เพราะว่าถ้าอาร์เรย์นั้นจัดเรียงอยู่แล้ว(ไม่ว่าจะมากไปน้อยหรือน้อยไปมากก็ตาม) ตอนที่แบ่งข้างโดยใช้จุดหลักนี้จะพบว่าข้างหนึ่งเป็นอาร์เรย์ว่างเสมอทำให้ไร้ประสิทธิภาพ

อ.ดร.วิษณุ โคตรจรัส

pivot

5

4

4

3

3

2

2

1

1

5

การเลือก pivot ที่ไม่ดี (ใช้ตัวแรกของสมาชิกอาร์เรย์)

pivot

ไม่มีด้านขวา

สมาชิกจะไปกองอยู่ข้างเดียวหมด นั้นคือแทนที่จะลดขนาดของปัญหาลงได้ครึ่งหนึ่ง กลับลดลงได้แค่หนึ่งหน่วย

อ.ดร.วิษณุ โคตรจรัส

pivot1
การเลือก pivot ที่ดี
  • เลือกpivotโดยใช้random number ส่วนใหญ่แล้วจะได้การแบ่งpartition สองข้างที่ดี
    • แต่ว่าวิธีนี้มีข้อเสียที่ว่าการสร้างrandom number นั้นเสียเวลาในตัวของมันเอง
  • ใช้ค่ามัธยฐานจากอาร์เรย์ช่องแรกกับช่องกลางและช่องสุดท้าย
    • จริงๆแล้วค่าpivot ที่จะทำให้แบ่งอาร์เรย์ได้เป็นสองข้างเท่ากันนั้นจะต้องเป็นค่ามัธยฐานจากทั้งอาร์เรย์
    • แต่จะมานั่งคิดค่านี้มันก็จะเสียเวลาเกินไปดังนั้นจึงได้มีการลองใช้ค่ามัธยฐานจากอาร์เรย์ช่องแรกกับช่องกลางและช่องสุดท้ายพบว่าได้ผลดีเช่นกัน

อ.ดร.วิษณุ โคตรจรัส

pivot median of 3
โค้ดการเลือก pivot โดยหา median of 3

1: private static int pivotIndex(int[] a, int l, int r){

2: int c = (l+r)/2;

3: if((a[l]<=a[r] && a[l]>=a[c]) ||

4: (a[l]>=a[r] && a[l]<=a[c]))

5: return l;

6: if((a[c]<=a[l] && a[c]>=a[r]) ||

7: (a[c]>=a[l] && a[c]<=a[r])

8: return c;

9: return r;

10: }

อ.ดร.วิษณุ โคตรจรัส

3 partition
ขั้นที่ 3: การแบ่ง partition
  • เอา pivot ที่เลือกได้แล้วออกไปให้พ้นทางโดยสลับที่กับสมาชิกตัวสุดท้ายของอาร์เรย์
  • ให้ตัวแปร i เป็น index ของตำแหน่งแรกของอาร์เรย์และตัวแปร j เป็น index ของตำแหน่งรองสุดท้ายของอาร์เรย์ (อย่าลืมว่าตอนนี้เราใช้ตำแหน่งสุดท้ายเก็บ pivot ไปแล้ว)
  • ดูตำแหน่งของ i กับ jในอาร์เรย์เป็นหลักให้เลื่อน i ไปทางขวาเรื่อยๆข้ามสมาชิกในอาร์เรย์ที่มีค่าน้อยกว่าค่าของ pivot แต่ต้องหยุดเมื่อเจอสมาชิกในอาร์เรย์ที่มีค่ามากกว่าหรือเท่ากับค่าของ pivot
  • ในทำนองเดียวกันให้เลื่อน j ไปทางซ้ายเรื่อยๆข้ามสมาชิกที่มีค่ามากกว่าค่าของ pivot และหยุดเมื่อเจอสมาชิกในอาร์เรย์ที่มีค่าน้อยกว่าหรือเท่ากับค่าของ pivot

อ.ดร.วิษณุ โคตรจรัส

slide50
ถ้า i ยังอยู่ด้านซ้ายของ j อยู่ก็สลับที่สมาชิกในอาร์เรย์สองตำแหน่งนั้นเสียนี่เป็นการเอาค่าน้อย(เมื่อเทียบกับ pivot)ไปไว้ข้างซ้ายและค่ามากไปไว้ด้านขวาของอาร์เรย์ส่วนกรณีถ้า i ไม่อยู่ทางด้านซ้ายของ j ให้ข้ามไปทำข้อ 8
  • เลื่อน i ไปทางขวาหนึ่งหน่วยและเลื่อน j ไปทางซ้ายหนึ่งหน่วยเพื่อหลบเลี่ยงช่องที่พึ่งมีการสลับที่สมาชิกไป
  • จากนั้นเริ่มทำจากข้อ 3 อีกครั้งหนึ่ง
  • ถ้ามาถึงขั้นตอนนี้ให้สลับที่สมาชิกที่อยู่ที่ตำแหน่ง i กับ pivot ก็จะได้อาร์เรย์ที่มี pivot อยู่ในตำแหน่งที่ถูกต้องด้านซ้ายจะมีสมาชิกที่มีค่าน้อยกว่าส่วนด้านขวาจะมีสมาชิกที่มีค่ามากกว่า

อ.ดร.วิษณุ โคตรจรัส

partition

7

7

7

4

2

2

2

9

6

5

5

5

1

3

1

1

8

0

0

0

8

8

9

9

6

6

3

3

4

4

j

j

i

i

มีต่อ

ตัวอย่างการแบ่ง partition

pivot

สลับที่ pivot กับตัวสุดท้าย

เลื่อน i ไปทางขวาและ j ไปทางซ้าย

ปรากฏว่าเลื่อนไปไม่ได้ทั้งคู่ต้องสลับที่ a[i] กับ a[j]

อ.ดร.วิษณุ โคตรจรัส

partition1

8

8

8

9

9

9

6

6

6

7

7

7

4

4

4

3

3

3

2

2

2

5

5

0

1

1

1

5

0

0

มีต่อ

ตัวอย่างการแบ่ง partition (ต่อ)

i

j

เลื่อน i ไปทางขวาและ j ไปทางซ้าย

i

j

สลับที่ a[i] กับ a[j]

i,j

อ.ดร.วิษณุ โคตรจรัส

partition 2

8

8

9

9

6

6

7

7

4

4

3

3

2

2

0

0

1

1

5

5

ตัวอย่างการแบ่ง partition (ต่อ 2)

i,j

เลื่อน i ไปทางขวาและ j ไปทางซ้าย

j

i

ตอนนี้ i ไม่น้อยกว่า j แล้วดังนั้นสลับตัวที่ i กับ pivot จะได้ผลลัพธ์

3

2

0

1

4

8

9

6

7

5

ข้างนี้น้อยกว่า 4 ทั้งหมด

ข้างนี้มากกว่า 4 ทั้งหมด

อ.ดร.วิษณุ โคตรจรัส

partition pivot 1

8

8

8

9

9

9

6

6

6

4

4

4

4

4

4

7

0

7

4

4

4

2

2

2

4

4

4

0

7

0

มีต่อ

การแบ่ง partition ของค่าที่เท่ากับ pivot: วิธีที่ 1

pivot

  • ถ้าเราทำให้i หยุดแต่j ข้ามจำนวนนั้น นี่ไม่นับว่าเป็นวิธีที่ดีเพราะว่าจำนวนที่เท่ากับpivot ทั้งหมดจะไปกองอยู่ในอาร์เรย์ข้างเดียว

i

j

เลื่อน i ไปทางขวาและ j ไปทางซ้าย

i

j

สลับที่ a[i] กับ a[j]

i

j

อ.ดร.วิษณุ โคตรจรัส

partition pivot 11

8

8

8

9

9

9

6

6

6

4

4

4

4

4

4

0

0

0

4

2

4

2

4

2

4

4

4

7

7

7

การแบ่ง partition ของค่าที่เท่ากับ pivot: วิธีที่ 1 (ต่อ)

i

j

เลื่อน i ไปทางขวาและ j ไปทางซ้าย

i

j

สลับที่ a[i] กับ a[j]

j

i

pivot จะมาสลับกับตัวนี้

อ.ดร.วิษณุ โคตรจรัส

partition pivot 2

1

1

1

1

1

1

1

1

1

1

การแบ่ง partition ของค่าที่เท่ากับ pivot: วิธีที่ 2
  • ให้ทั้ง i และ j ข้ามค่าที่เท่ากับ pivot ไปให้หมด
  • ก็ยังไม่ดีพอ เพราะ ในกรณีที่สมาชิกอาร์เรย์เท่ากันหมด

i

j

i กับ j เลื่อนไปจนสุดอาร์เรย์ ทำให้ pivot ไปอยู่ที่ปลายอาร์เรย์ การแบ่งข้างจึงไม่สมดุล

อ.ดร.วิษณุ โคตรจรัส

partition pivot 3
การแบ่ง partition ของค่าที่เท่ากับ pivot: วิธีที่ 3
  • ให้i และj หยุดลงทั้งคู่เมื่อเจอค่าที่เท่ากับpivot
  • ในกรณีนี้จะเกิดการสลับที่ของจำนวนที่เท่ากันโดยเปล่าประโยชน์
  • ถ้าเราดูอาร์เรย์ในหน้าที่แล้วจะเห็นว่ามีการสลับที่ทุกขั้นตอน
  • แต่จะมีข้อดีคืออาร์เรย์จะถูกแบ่งเป็นสองข้างเท่าๆกันถ้าเทียบกับวิธีที่สอง
  • แม้วิธีนี้จะมีการสลับที่โดยไร้ประโยชน์แต่ก็ยังเร็วกว่าเพราะแบ่งอาร์เรย์เป็นสองซีกเท่าๆกัน

อ.ดร.วิษณุ โคตรจรัส

quick sort2
โค้ดของ quick sort

private static void quicksort(int[] a,int l, int r){

if(l+CUTOFF<=r)

{

//ก่อนอื่นต้องหา pivot

int pIndex = pivotIndex(a,l,r);

//เอา pivot ออกไปให้พ้นทาง โดยสลับกับท้ายอาร์เรย์

swap(a,pIndex,r);

int pivot = a[r];

อ.ดร.วิษณุ โคตรจรัส

slide59

ตอนเลื่อน index ก็ต้องระวังไม่

ให้ตกอาร์เรย์ด้วย

//เริ่มการแบ่งข้าง

int i=l, j=r-1;

for( ; ; )

{

while(i<r && a[i]<pivot)i++;

while(j>l && a[j]>pivot)j--;

if(i<j){

swap(a,i,j);

i++;

j--;

}else //ถ้า i เลย j แล้วก็สลับไม่ได้แล้ว ให้ออกจากลูป

break;

}

สลับที่

อ.ดร.วิษณุ โคตรจรัส

slide60
//สลับที่ pivot ไปที่ที่ถูกต้อง

swap(a,i,r);

//เรียก quick sort ของอาร์เรย์ย่อยสองข้าง

quicksort(a,l,i-1);

quicksort(a,i+1,r);

}

else

insertionSort(a,l,r);

}

อ.ดร.วิษณุ โคตรจรัส

quicksort
โค้ด quicksort ยังปรับได้อีก
  • เราสามารถทำให้ quick sort เร็วกว่าในตัวอย่าง
  • โดยตอนที่หา pivot
    • ให้จัดเรียงตัวเลขจากในช่องแรก ช่องกลาง และช่องสุดท้ายของอาร์เรย์ในตอนนั้นเลย
    • แล้วตอนที่เอา pivot ออกไปให้พ้นทางก็เอาสลับที่กับตัวรองสุดท้ายของอาร์เรย์(แทนที่จะเป็นตัวสุดท้าย)
  • ลองไปทำดู และเทียบเวลาของวิธีนี้กับวิธีที่สอน
    • เมื่อข้อมูลที่ต้องการจัดเรียงเป็น 2,3,4,…,n-1,n,1
    • เมื่อข้อมูลเรียงจากมากไปน้อย

อ.ดร.วิษณุ โคตรจรัส

quick sort3
เวลาในการทำงานของ quick sort
  • เราจะถือว่าใช้ random pivot และไม่ใช้ insertion sort เมื่ออาร์เรย์มีขนาดเล็ก
  • เล็ก ให้ T(n) = เวลาในการทำงานของโปรแกรมเมื่อมีอาร์เรย์ขนาด n เราให้ T(0)=1, T(1)=1
  • สำหรับในกรณีอื่น เวลาของโปรแกรมจะเกิดจากผลรวมของ
    • เวลาในการหา pivot ->คงที่ ตัดทิ้งได้
    • เวลาในการแบ่ง partition ซึ่งแปรผันตรงกับขนาดของอาร์เรย์ เราให้เวลานี้เท่ากับ c*n
    • เวลาในการทำ quick sort ของสองข้าง ให้ข้างซ้ายมีขนาดอาร์เรย์เป็น i

อ.ดร.วิษณุ โคตรจรัส

slide63

เวลาในการทำงานของ quick sort (ต่อ)

สมการเวลาในรูปแบบทั่วไปจะเป็น

อ.ดร.วิษณุ โคตรจรัส

worst case1

มีต่อ

Worst case
  • จะเกิดเมื่อ pivot เป็นจำนวนที่น้อยที่สุดเสมอ ดังนั้นการแบ่ง partition จะทำให้เกิดอาร์เรย์ที่ขนาดลดลงไปเพียงหนึ่งในแต่ละครั้ง สมการของเราจะได้

=1 ตัดทิ้งได้

อ.ดร.วิษณุ โคตรจรัส

worst case2

มีต่อ

Worst case (ต่อ)

เอามาบวกกันหมด จะได้

อ.ดร.วิษณุ โคตรจรัส

worst case 2
Worst case (ต่อ 2)
  • สรุปคือ เวลา worst case ก็ใกล้เคียงกับเวลาของ sort แบบอื่นๆ

อ.ดร.วิษณุ โคตรจรัส

best case

มีต่อ

Best case
  • กรณีนี้เกิดขึ้นเมื่อแบ่งข้างอาร์เรย์ได้สองข้างเท่าๆกัน
    • สมมติให้ แบ่งอาร์เรย์ได้สองข้างเท่ากันเสมอ
    • วิธีทำจะเหมือนกับกรณีที่เราหาเวลาในการทำงานของ merge sort
  • สมการจะเป็น

อ.ดร.วิษณุ โคตรจรัส

best case1

มีต่อ

Best case (ต่อ)

บวกกันหมด

อ.ดร.วิษณุ โคตรจรัส

best case 2
Best case (ต่อ 2)
  • อยู่ในระดับเดียวกับ merge sort

อ.ดร.วิษณุ โคตรจรัส

average case

มีต่อ

Average case
  • ขนาดของอาร์เรย์ย่อยข้างหนึ่งอาจเป็น 0 หรือ 1 หรือ 2 หรือ 3 เป็นไปได้จนถึง n-1 เลยทีเดียว
    • อาร์เรย์ย่อยจะมีขนาด n ไม่ได้ อย่าลืมว่าเราไม่นับตัว pivot
    • ฉะนั้นถ้าให้แต่ละขนาดมีความเป็นไปได้ที่จะเกิดขึ้นเท่าๆกัน จะได้ว่าแต่ละขนาดมีความเป็นไปได้ = 1/n
  • ดังนั้น เราสามารถเขียนสมการได้เป็น

อ.ดร.วิษณุ โคตรจรัส

average case1

มีต่อ

Average case (ต่อ)
  • เอาสมการในหน้าที่แล้วมา คูณ n เข้าไปจะได้

(avg1)

  • เปลี่ยน n เป็น n-1จะได้

(avg2)

อ.ดร.วิษณุ โคตรจรัส

average case 2

มีต่อ

Average case (ต่อ 2)
  • เอา (avg1)-(avg2) จะได้
  • ตัดค่า c ซึ่งเป็นตัวไม่สำคัญออก แล้วหารด้วย n(n+1)เราจะได้

อ.ดร.วิษณุ โคตรจรัส

average case 3

มีต่อ

Average case (ต่อ 3)
  • เราจะได้ชุดสมการดังนี้

เอานี่กับตัวสุดท้าย

ของหน้าที่แล้วมา

บวกกัน

อ.ดร.วิษณุ โคตรจรัส

average case 4

มีต่อ

Average case (ต่อ 4)
  • จะได้

(avg3)

  • ซึ่งตัวผลบวกนั้นเป็น harmonic number ซึ่งมีสูตรดังนี้

อ.ดร.วิษณุ โคตรจรัส

average case 5
Average case (ต่อ 5)
  • ถ้าแทนค่า harmonic number ลงใน avg3 จะได้
  • ข้างขวาของสมการนั้นมี ln n เป็นหลัก
    • ดังนั้นเป็น O(log n)
  • เพราะฉะนั้นพอเราย้าย n+1 มาคูณข้างซ้าย ก็จะเห็นว่า

อ.ดร.วิษณุ โคตรจรัส

bucket sort
Bucket sort
  • เรารู้ว่าข้อมูลจะอยู่ตำแหน่งไหนตั้งแต่แรก ดังนั้นไม่ต้องมีการเปรียบเทียบสมาชิกกันเลย
  • ตัวอย่างเช่นการเรียงไพ่ทั้ง 52 ใบ เรารู้อยู่แล้วว่าไพ่ใดจะอยู่ตำแหน่งไหน
    • ดังนั้นก็แค่ทำที่ไว้สำหรับไพ่แต่ละใบ
    • ในตอนที่เลือกไพ่ใบหนึ่ง ก็แค่เอาไพ่ใบนั้นใส่ในที่ที่จองไว้ให้มัน
    • อย่างนี้พอหยิบแต่ละใบ ก็ถือว่าใบนั้นเรียงเข้าถูกที่แล้ว
    • ดังนั้นเวลาในการจัดเรียงก็ย่อมเป็น O(n) แน่ๆ
    • ที่ของไพ่แต่ละใบก็จะถือเป็นหนึ่ง bucket (ตะกร้า) ซึ่งในกรณีแบบนี้ หนึ่ง bucket จะจุของได้หนึ่งอย่าง

อ.ดร.วิษณุ โคตรจรัส

slide77

Bucket sort (ต่อ)

  • ถ้าเรามีตัวเลขตั้งแต่ 1 ถึง m โดยมี n จำนวน (n<m)
  • เราสามารถจัดเรียงจำนวนเหล่านี้ได้โดยทำอาร์เรย์ขนาด m ขึ้นมา
  • ให้ตอนแรกทุกสมาชิกของอาร์เรย์นี้มีค่าเป็น 0
    • พอเราอ่านตัวเลขที่ยังไม่เรียงทีละตัว เจอตัวเลข k ก็ไปเพิ่มค่าใน a[k] ไปหนึ่ง
    • ดังนั้นพอเราอ่านจบก็จะได้อาร์เรย์ที่บอกถึงการจัดเรียง (นับcounter)
    • ต่อจากนั้นเราก็อ่านอาร์เรย์นี้แล้วพิมพ์ตัวเลขออกมา
  • เวลาที่ใช้ก็จะเป็น O(n) สำหรับการอ่านข้อมูลตอนแรก และ O(m) สำหรับการพิมพ์คำตอบ
    • ดังนั้นตัวอย่างนี้จะมีค่าเวลาโดยรวมเป็น O(n+m)

อ.ดร.วิษณุ โคตรจรัส

slide78

Bucket sort (ต่อ 2)

  • เราอาจให้หนึ่ง bucket จุของได้หลายชิ้นที่ไม่เหมือนกันก็ได้ แล้วค่อยหาทางอื่นจัดเรียงของใน bucket อีกทีหนึ่ง
  • เช่น การจัดเรียงข้อสอบของนักเรียน 49 คน
    • ในตอนที่เก็บข้อสอบ ครูก็สามารถแบ่งนักเรียนออกเป็นห้ากลุ่มได้ (กลุ่มคือ bucket นั่นเอง) โดยดูจากหลักสิบของเลขที่สอบเป็นหลัก
    • ภายในกลุ่มเราสามารถใช้ insertion sort จัดได้ หลังจากนั้นก็เอาแต่ละกลุ่มที่จัดแล้วมาเรียงกัน ก็จะได้คำตอบเลย
  • เวลาที่ใช้จะขึ้นอยู่กับวิธีที่ใช้จัดเรียงของภายในแต่ละ bucket

อ.ดร.วิษณุ โคตรจรัส

radix sort

143

002

013

328

165

มีต่อ

Radix sort
  • ถือเป็น bucket sort แบบหนึ่ง
  • นี่คือการทำ bucket sort หลายที
    • โดยแต่ละทีเราจะใช้ส่วนหนึ่งของข้อมูลเป็นตัวกำหนด bucket
  • ตัวอย่างเช่นการจัดเรียงตัวเลข
    • (ต้องให้ตัวเลขมีจำนวนหลักเท่ากันดังนั้นจึงต้องเติมศูนย์ลงไปสำหรับตัวเลขที่มีจำนวนหลักน้อย)

อ.ดร.วิษณุ โคตรจรัส

slide80

143

002

002

143

013

013

328

165

165

328

มีต่อ

Radix sort (ต่อ)

  • เราอ่านอาร์เรย์ข้างบนจากซ้ายไปขวา แบ่งเป็น bucket โดยใช้หลักหน่วยจัดเรียงก่อน
  • จะได้ bucket ของหลักหน่วยที่เป็น 0 ไปจนถึงหลักหน่วยที่เป็น 9 (ตัด bucket ของหลักที่ไม่มีทิ้งไป)
    • 002
    • 143,013
    • 165
    • 328

รวมเป็นอาร์เรย์อีก

อ.ดร.วิษณุ โคตรจรัส

slide81

002

002

143

013

013

328

165

143

328

165

มีต่อ

Radix sort (ต่อ 2)

  • ทำต่อโดยอ่านอาร์เรย์จากซ้ายไปขวา แบ่งเป็น bucket ตามหลักสิบ ได้
    • 002
    • 013
    • 328
    • 143
    • 165

รวมเป็นอาร์เรย์อีก

อ.ดร.วิษณุ โคตรจรัส

slide82

002

002

013

013

143

328

165

143

328

165

Radix sort (ต่อ 3)

  • ทำต่อ นี่เป็นการจัดครั้งสุดท้าย เพราะจำนวนหลักมีแค่นี้
  • แบ่งเป็น bucket ตามหลักร้อย ได้
    • 002,013
    • 143,165
    • 328

รวมเป็นอาร์เรย์อีก

เรียงเรียบร้อย

อ.ดร.วิษณุ โคตรจรัส

slide83
โค้ดการหาค่าหลักที่ d ของตัวเลข n

public static int digitTh(int n, int d){

if (d == 0)

return n%10;

else

return digitTh(n/10,d-1);

}

เวลาเป็น O(d)

อ.ดร.วิษณุ โคตรจรัส

10 bucket d

มีต่อ

โค้ดของการแบ่งอาร์เรย์เป็น 10 bucket โดยใช้หลักที่ d เป็นตัวกำหนด

public static void bucketing(int data[], int d){

int i,j,value;

//เราจะให้มี 10 bucket โดยแต่ละ bucket เป็น

//vector (อาร์เรย์ที่โตได้)

Vector bucket[] = new Vector[10];

for(j=0;j<10;j++)

bucket[j] = new Vector();

อ.ดร.วิษณุ โคตรจรัส

slide85

มีต่อ

//จับของใส่ bucket ตามหลัก

int n =data.length;

for(i=0;i<n;i++){

value = data[i];

j = digitTh(value,d);

bucket[j].add(new Integer(value));

}

อ.ดร.วิษณุ โคตรจรัส

slide86
//เอาใส่อาร์เรย์อีกโดยใส่ย้อนจากหลังมาหน้า//เอาใส่อาร์เรย์อีกโดยใส่ย้อนจากหลังมาหน้า

i=n;

for(j=9;j>=0;j--){

while(!bucket[j].isEmpty()){

i- -;

value=

((Integer)bucket[j].remove()).intValue();

data[i]=value;

}

}

}

อ.ดร.วิษณุ โคตรจรัส

radix sort1
โค้ดของ radix sort

public static void radixSort(int data[], int size){

for(int j=0;j<size; j++)

bucketing(data,j);

}

อ.ดร.วิษณุ โคตรจรัส

slide88
การเปรียบเทียบวัตถุใน Java

public boolean equals(Object obj)

  • ถ้าเรามี x.equals(y); โค้ดนี้จะ return true เมื่อ x กับ y เป็นวัตถุเดียวกันเท่านั้น มิฉะนั้นจะ return false
  • เปรียบเทียบสิ่งของที่เป็นสิ่งเดียวกันเท่านั้น (reference เดียวกัน)
  • บอกว่าน้อยกว่ามากกว่าไม่ได้เลย
  • มีหลายคลาสที่ overwrite เมธอดนี้เพื่อให้เทียบกับวัตถุอื่นที่มีค่าภายในเท่ากันได้ด้วย ยกตัวอย่างเช่น คลาส String

อ.ดร.วิษณุ โคตรจรัส

slide89
การเปรียบเทียบวัตถุใน Java (ต่อ)
  • Comparable Interface
  • โดยคลาสที่จะอิมพลีเม้นท์ตัวอินเตอร์เฟสนี้จะต้องมีเมธอด
    • public int compareTo(Object o)
  • เปรียบเทียบ this object กับวัตถุที่เป็น argument
    • return ค่าลบถ้า this object มีค่าน้อยกว่าตัวที่เป็น argument
    • return ค่าบวกถ้า this object มีค่ามากกว่าตัว argument
    • ค่า 0 ถ้า วัตถุที่เราเปรียบเทียบมีค่าเท่ากัน

อ.ดร.วิษณุ โคตรจรัส

java 2
การเปรียบเทียบวัตถุใน Java (ต่อ 2)
  • Comparator Interface
  • โดยคลาสที่จะอิมพลีเม้นท์ตัวอินเตอร์เฟสนี้จะต้องมีเมธอด

public int compare(Object o1, Object o2)

  • เปรียบเทียบ o1 กับ o2 ว่ามีค่ามากน้อยกว่ากันเท่าไร
    • return ค่าลบถ้า o1 มีค่าน้อยกว่าo2
    • return ค่าบวกถ้า o1 มีค่ามากกว่า o2
    • ค่า 0 ถ้า o1 กับ o2 มีค่าเท่ากัน

อ.ดร.วิษณุ โคตรจรัส

java 3
การเปรียบเทียบวัตถุใน Java (ต่อ 3)
  • ต้องมี method ที่สองด้วยคือ

public boolean equals(Object obj)

  • ซึ่งจะใช้ในการเปรียบเทียบ Comparator ตัวนี้(this) กับอีกตัวหนึ่ง
    • เมธอดนี้ return true เมื่อobj เป็น Comparator ซึ่งมีการจัดเรียงวัตถุเหมือนกับ this
  • อินเตอร์เฟสนี้สามารถใช้ได้แบบเดียวกับ Comparator เลย
  • แต่มักนิยมใช้เป็น argument ของคลาสต่างๆเพื่อที่จะสามารถปรับเปลี่ยนวิธีการเปรียบเทียบได้โดยง่าย

อ.ดร.วิษณุ โคตรจรัส

slide92
จบ เรื่องอาร์เรย์และการจัดเรียงข้อมูล

อ.ดร.วิษณุ โคตรจรัส