การคัดแยกทางพยาธิวิทยา


15

การคัดแยกทางพยาธิวิทยา

หัวหน้าของคุณต้องการให้คุณพัฒนาอัลกอริทึมการเรียงลำดับเพื่อปรับปรุงประสิทธิภาพของแอปพลิเคชันของ บริษัท ของคุณ อย่างไรก็ตามเมื่อเขียนใบสมัครแล้วคุณก็รู้ว่าคุณไม่น่าจะสามารถทำให้เร็วขึ้นได้ ไม่ต้องการทำให้หัวหน้าของคุณผิดหวังคุณตัดสินใจที่จะพัฒนาอัลกอริธึมใหม่ที่ทำงานได้ดีกว่า * เรียงลำดับตามชุดข้อมูลบางชุด แน่นอนคุณไม่สามารถทำให้ชัดเจนว่าอัลกอริทึมทำงานในบางกรณีเท่านั้นดังนั้นคุณต้องการทำให้ชัดเจนที่สุด

วัตถุประสงค์ของการประกวดนี้คือการเขียนขั้นตอนการเรียงลำดับในภาษาที่คุณเลือกซึ่งมีประสิทธิภาพดีกว่าในชุดข้อมูลบางชุดมากกว่าชุดอื่น ๆ พร้อมผลลัพธ์ที่ทำซ้ำได้ การจำแนกประเภทที่เจาะจงมากขึ้นนั้นเป็นตัวกำหนดความเร็ว อัลกอริทึมจะต้องทำการเรียงลำดับบางอย่างดังนั้นอัลกอริทึมที่ขึ้นอยู่กับข้อมูลที่ถูกจัดเรียงอย่างสมบูรณ์แล้ว (เช่นในอัลกอริทึมที่ไม่ได้ทำอะไรเลย) หรืออัลกอริทึมที่ขึ้นอยู่กับข้อมูลที่เรียงลำดับแบบย้อนกลับ อัลกอริทึมการเรียงลำดับต้องเรียงลำดับชุดข้อมูลใด ๆ อย่างถูกต้อง

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

ตัวอย่างเช่นหนึ่งอาจส่งอัลกอริทึมการเรียงลำดับการแทรกด้วยข้อมูลที่ดีเป็นข้อมูลที่เกือบจะเรียงแล้วและข้อมูลไม่ดีเป็นข้อมูลแบบสุ่มอย่างสมบูรณ์เนื่องจากการเรียงลำดับการแทรกวิธีการ O (n) กับข้อมูลที่เกือบเรียง อย่างไรก็ตามสิ่งนี้ไม่ดีมากเนื่องจากหัวหน้าของฉันอาจสังเกตว่าข้อมูลการทดสอบทั้งหมดเกือบเรียงกันเพื่อเริ่มต้น

นี่คือการดังนั้นคำตอบที่ได้คะแนนมากที่สุดหลังจาก 7 วัน (21 พฤษภาคม) จะเป็นผู้ชนะ

หากไม่มีใครชนะฉันฉันต้องการส่งคำตอบ wiki ชุมชนที่ใช้ประโยชน์จากชุดข้อมูลที่กระจายอย่างสม่ำเสมอ


อาจเป็นประโยชน์ / แหล่งข้อมูลที่น่าสนใจสำหรับผู้ที่เข้าใกล้คำถามนี้: "อัลกอริทึมการเรียงลำดับ Psychic" (คำเตือน: ผู้เขียนบทความนั้นและฉันอยู่ใกล้มาก :-P)
HostileFork พูดว่าอย่าไว้วางใจ SE

คำตอบ:


9

มันนานมากแล้ว แต่ฉันจำย้อนกลับไปในอัลกอริทึม 101 เราได้รับการสอนอัลกอริทึมการเรียงลำดับที่ใช้การสุ่ม ฉันไม่ได้เป็นนักเรียนที่ดีมากดังนั้นฉันจำไม่ได้ว่ามันเป็นอย่างไรหรือทำไมมันถึงทำงานได้อย่างรวดเร็วโดยเฉลี่ย

อย่างไรก็ตามฉันได้ตัดสินใจแล้วว่าปัญหานี้เรียกร้องให้มีวิธีแก้ปัญหาที่ใช้การสุ่มซึ่งหวังว่าจะได้ผลโดยเฉลี่ย

import random

def arrayIsSorted (arr) :
    for i in range(len(arr)-1) :
        if arr[i]>arr[i+1] : return False
    return True

def rSort (arr) :
    random.seed (42)
    counter = 0
    while not arrayIsSorted(arr) :
        random.shuffle (arr)
        counter+=1
    print ("Sorted in %d iterations." % counter)
    return arr

เนื่องจากการสุ่มอย่างแท้จริงเป็นสิ่งสำคัญฉันต้องแน่ใจว่าได้เพาะเชื้อ RNG ด้วยคำตอบของชีวิตจักรวาลและทุกสิ่ง หลังจากการทดสอบนิดหน่อยปรากฎว่านั่นเป็นการเคลื่อนไหวที่ชาญฉลาด! ตรวจสอบความรวดเร็วของการเรียงลำดับโดยพลการของทั้ง 2 รายการ:

rSort ([6,1,4,2,3,7,5])
rSort ([8,9,6,1,4,7,2,3,5])

ทั้งสองอย่างนี้จัดเรียงในการวนซ้ำเพียง 1 ครั้ง - คุณอาจไม่สามารถขอฟังก์ชั่นที่เร็วกว่านี้ได้!

ตอนนี้เป็นที่ยอมรับรายการอื่น ๆ บางรายการให้ผลลัพธ์ที่แย่กว่าเล็กน้อย ...

rSort ([5,1,4,2,3,7,6])
rSort ([8,9,6,1,4,7,2,5,3])

สิ่งเหล่านี้เรียงลำดับซ้ำใน 4,176 และ 94,523 ตามลำดับซึ่งจริง ๆ แล้วใช้เวลามากกว่าหนึ่งวินาที ... แต่ขอเพียงแค่ให้ความจริงนั้นกับตัวเราเองเพื่อที่จะไม่เบี่ยงเบนความสนใจจากอัลกอริทึมนี้!

แก้ไข:

ฉันถูกขอให้พิสูจน์ประสิทธิภาพของอัลกอริทึมในรายการ 100 รายการดังนั้นคุณจะไปที่นี่:

rSort ([70, 6, 52, 97, 85, 61, 62, 48, 30, 3, 11, 88, 39, 91, 98, 8, 54, 92, 44, 65, 69, 21, 58, 41, 60, 76, 27, 82, 93, 81, 20, 94, 22, 29, 49, 95, 40, 19, 55, 42, 43, 1, 0, 67, 35, 15, 51, 31, 16, 25, 5, 53, 37, 74, 86, 12, 13, 72, 56, 32, 47, 46, 59, 33, 80, 4, 45, 63, 57, 89, 7, 77, 14, 10, 34, 87, 18, 79, 9, 66, 24, 99, 64, 26, 78, 38, 90, 28, 83, 75, 68, 2, 17, 73, 96, 71, 23, 84, 36, 50])

แม้แต่รายการที่ยาวและสมบูรณ์แบบนี้ก็จะถูกจัดเรียงทันที! แท้จริงฉันต้องสะดุดกับอัลกอริธึมการเรียงลำดับที่ดีที่สุดในโลก!


3
เราสามารถรับผลการทดสอบจากชุดข้อมูลที่ใหญ่กว่านี้ได้ไหม? อาจเป็นหนึ่งเดียวกับ 100 องค์ประกอบ? ;)
Geobits

@Geobits ไม่มีปัญหานี่มันคือ :)
Tal Tal

1
@Geobits ใช่มันเป็นเช่นนั้น ในที่สุด
Tal

3
มันยืดออกไป แต่มันอาจจะเป็นที่ถกเถียงกันอยู่ว่ามันใช้โบกี้ซึ่งในที่สุดจะเรียงลำดับอาเรย์ให้เวลาพอ ฉันยินดีที่จะเดิมพันว่า 'การสุ่มและเล่นซ้ำ' มีคุณสมบัติเหมือนการเล่นเกมแม้ว่าจะไม่ได้รับการจัดเรียงที่ดี
millinon

1
ถ้ามันเป็นการสุ่มแบบสุ่มอย่างแท้จริง PRNG มีวงรอบดังนั้นฉันไม่สามารถเห็นได้ว่าคุณจะรับประกันการเรียงสับเปลี่ยนทั้งหมดได้อย่างไร
Geobits

2

หากคุณสามารถสร้างข้อมูลของคุณเองมันก็ค่อนข้างตรงไปตรงมา - รับข้อมูลที่ดูสุ่ม แต่มีคีย์สำหรับการเรียงลำดับที่เร็วขึ้น ข้อมูลอื่น ๆ ทั้งหมดใช้วิธีการเรียงลำดับดั้งเดิมดังนั้นเวลาเฉลี่ยจะดีกว่า

วิธีง่ายๆวิธีหนึ่งคือตรวจสอบให้แน่ใจว่ารายการข้อมูลแต่ละรายการมีคีย์ที่ไม่ซ้ำกันและจากนั้นเพียงแค่กดแป้น ยกตัวอย่างเช่นรายการที่มีตัวเลขตั้งแต่ 1-10,000 คูณด้วย 16 และมีหมายเลขสุ่มจาก 0-15 ที่เพิ่มเข้าไป (ดูfillArray ()ด้านล่าง) พวกเขาจะดูสุ่ม แต่แต่ละคนมีคีย์ตามลำดับที่ไม่ซ้ำกัน สำหรับการเรียงลำดับให้หารด้วย 16 (ใน C >> >> เร็วมาก) จากนั้นให้วางตัวเลขลงในอาร์เรย์โดยใช้คีย์ผลลัพธ์เป็นดัชนี หนึ่งรอบและคุณทำเสร็จแล้ว ในการทดสอบฉันพบว่าการเรียงลำดับความเร็วช้ากว่าตัวเลขสิบล้านครั้ง 30 ล้านครั้ง

void fillArray(int *a,int len)
{
  for (int i=0;i<len;++i)
    a[i]=(i<<4)|(rand()&0xF);
  // shuffle later
}
void sortArray(int *a,int len)
{
  int key=0;
  int *r=new int[len];
  for (int i=0;i<len;++i)
  {
    key=a[i]>>4;
    r[key]=a[i];
  }
  memcpy(a,r,len*sizeof(int));
  delete[] r;
}
void shuffleArray(int *a,int len)
{
  int swap=0, k=0;
  for (int i=0;i<len;++i)
  {
    k=rand()%len;
    swap=a[k];
    a[k]=a[i];
    a[i]=swap;
  }
}
int qCompare(const void*a,const void*b)
{
  int result=*((int*)a)-*((int*)b);
  return result;
}
void main()
{
  int aLen=10000;
  int *a=new int[aLen];
  srand (time(NULL));
  fillArray(a,aLen);
  // time them
  long t0=0, d0=0, d1=0;
  // qsort
  shuffleArray(a,aLen);
  t0=::GetTickCount();
  qsort(a,aLen,sizeof(int),&qCompare);
  d0=::GetTickCount()-t0;
  // oursort
  shuffleArray(a,aLen);
  t0=::GetTickCount();
  sortArray(a,aLen);
  d1=::GetTickCount()-t0;
  delete[] a;
}

สิ่งใดก็ตามที่มีคีย์เฉพาะสามารถจัดเรียงได้ด้วยวิธีนี้ - ถ้าคุณมีหน่วยความจำสำหรับเก็บมันแน่นอน ตัวอย่างเช่นฐานข้อมูลจำนวนมากใช้รหัสลูกค้าที่ไม่ซ้ำกัน - หากรายการมีขนาดเล็ก / เรียงลำดับมากพออาจมีหน่วยความจำอยู่ หรือวิธีอื่นในการแปลระเบียนเป็นหมายเลขเฉพาะ สำหรับข้อมูลเพิ่มเติมให้ค้นหา Hash Sorts เพราะนี่คือสิ่งที่ ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.