Phân loại bệnh lý


15

Phân loại bệnh lý

Sếp của bạn đã yêu cầu bạn phát triển một thuật toán sắp xếp để cải thiện hiệu suất của ứng dụng của công ty bạn. Tuy nhiên, khi đã viết đơn, bạn biết rằng bạn khó có thể làm cho nó nhanh hơn đáng kể. Không muốn làm sếp thất vọng, bạn đã quyết định phát triển một thuật toán mới hoạt động thậm chí còn tốt hơn * sắp xếp trên một số bộ dữ liệu nhất định. Tất nhiên, bạn không thể làm rõ rằng thuật toán chỉ hoạt động trong một số trường hợp, vì vậy bạn muốn làm cho nó tối nghĩa nhất có thể.

Mục tiêu của cuộc thi này là viết một thói quen sắp xếp theo ngôn ngữ bạn chọn, thực hiện tốt hơn trên một số bộ dữ liệu nhất định so với các bộ khác, với kết quả lặp lại. Phân loại càng cụ thể xác định tốc độ, càng tốt. Thuật toán phải thực hiện sắp xếp một số loại, do đó, thuật toán phụ thuộc vào dữ liệu đã được sắp xếp hoàn chỉnh (như trong thuật toán không có gì) hoặc thuật toán phụ thuộc vào dữ liệu được sắp xếp hoàn toàn ngược lại, đều không hợp lệ. Thuật toán sắp xếp phải sắp xếp chính xác bất kỳ bộ dữ liệu.

Sau khi trình bày thói quen của bạn, vui lòng bao gồm giải thích lý do tại sao nó chỉ hoạt động trên một số bộ dữ liệu nhất định và bao gồm kiểm tra chạy trên ít nhất một bộ dữ liệu tốt (nhanh) và một bộ dữ liệu xấu (chậm). Vấn đề ở đây là có thể chứng minh với sếp của bạn rằng bạn đã tình cờ tìm ra cách sắp xếp tốt hơn, do đó, nhiều dữ liệu kiểm tra sẽ tốt hơn. Tất nhiên, bạn sẽ chỉ cho sếp xem kết quả kiểm tra từ dữ liệu tốt, do đó lỗ hổng trong dữ liệu kiểm tra bắt buộc không thể quá rõ ràng. Nếu áp dụng cho ngôn ngữ của bạn, vui lòng cho thấy thuật toán của bạn nhanh hơn thuật toán sắp xếp tích hợp trong ngôn ngữ của bạn.

Ví dụ: người ta có thể gửi thuật toán sắp xếp chèn, với dữ liệu tốt là dữ liệu đã được sắp xếp gần và dữ liệu xấu là dữ liệu hoàn toàn ngẫu nhiên, do sắp xếp chèn tiếp cận O (n) trên dữ liệu gần như được sắp xếp. Tuy nhiên, điều này không tốt lắm, vì sếp của tôi có thể sẽ nhận thấy rằng tất cả các dữ liệu thử nghiệm gần như được sắp xếp để bắt đầu.

Đây là một , vì vậy câu trả lời có nhiều phiếu nhất sau 7 ngày (21 tháng 5) sẽ thắng.

Nếu không ai đánh bại tôi, tôi muốn gửi câu trả lời wiki cộng đồng, tận dụng các bộ dữ liệu được phân phối thống nhất.


Có thể là tài nguyên hữu ích / thú vị cho những người tiếp cận câu hỏi này: "Thuật toán sắp xếp tâm linh" (Tuyên bố miễn trừ trách nhiệm: tác giả của bài báo đó và tôi rất thân thiết. :-P)
HostileFork nói không tin tưởng SE

Câu trả lời:


9

Đó là một thời gian khá dài, nhưng tôi nhớ lại trong Thuật toán 101, chúng tôi đã được dạy một số thuật toán sắp xếp sử dụng ngẫu nhiên. Tôi không phải là một học sinh giỏi vì vậy tôi không thực sự nhớ nó đã đi như thế nào hoặc tại sao nó hoạt động nhanh chóng trung bình.

Tuy nhiên, tôi đã quyết định rằng vấn đề này đòi hỏi một giải pháp sử dụng ngẫu nhiên, hy vọng sẽ có tác dụng trung bình.

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

Vì ngẫu nhiên thực sự rất quan trọng, tôi đảm bảo gieo mầm RNG với câu trả lời cho Cuộc sống, Vũ trụ và Mọi thứ. Sau một chút thử nghiệm, hóa ra đó là một bước đi thông minh! Kiểm tra xem 2 danh sách hoàn toàn tùy ý này được sắp xếp nhanh như thế nào:

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

Cả hai đều được sắp xếp chỉ trong 1 lần lặp - bạn không thể yêu cầu chức năng nhanh hơn thế!

Bây giờ, thừa nhận, một số danh sách khác tạo ra kết quả tồi tệ hơn một chút ...

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

Chúng được sắp xếp theo thứ tự lần lượt là 4.176 và 94.523 lần, thực sự mất hơn một giây ... nhưng chúng ta hãy giữ sự thật đó cho chính mình để không làm sao lãng bất kỳ ai khỏi thuật toán tuyệt vời này!

Biên tập:

Tôi đã được yêu cầu chứng minh tính hiệu quả của thuật toán của mình trong danh sách 100 mục, vì vậy bạn hãy vào đây:

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])

Ngay cả danh sách dài và hoàn toàn tùy ý này được sắp xếp ngay lập tức! Thực sự tôi đã vấp phải thuật toán sắp xếp tốt nhất trên thế giới!


3
Chúng tôi có thể nhận được một số kết quả thử nghiệm trên bộ dữ liệu lớn hơn một chút không? Có lẽ một với 100 yếu tố? ;)
Geobits

@Geobits Không có vấn đề gì, đây là :)
Tal

1
@Geobits Có. Cuối cùng.
Tal

3
Đó là một sự kéo dài, nhưng có thể lập luận rằng nó sử dụng bogosort, cuối cùng sẽ sắp xếp mảng, cho đủ thời gian. Tôi sẵn sàng đặt cược rằng 'xáo trộn và lặp lại' đủ điều kiện là hợp nhất, mặc dù không được sắp xếp tốt.
millinon

1
Nếu đó là sự xáo trộn ngẫu nhiên thực sự, có lẽ. PRNG có một chu kỳ, vì vậy tôi không thể thấy làm thế nào bạn có thể đảm bảo tất cả các hoán vị được thử.
Geobits

2

Nếu bạn có thể tạo dữ liệu của riêng mình, thì điều đó khá đơn giản - nhận dữ liệu có vẻ ngẫu nhiên, nhưng bao gồm một khóa để sắp xếp nhanh hơn. Tất cả các dữ liệu khác sử dụng phương pháp sắp xếp ban đầu, vì vậy thời gian trung bình là tốt hơn.

Một cách dễ dàng là đảm bảo mỗi mục dữ liệu có một khóa duy nhất và sau đó chỉ cần băm các khóa. Lấy ví dụ một danh sách với các số từ 1-10.000, tất cả được nhân với 16 và với một số ngẫu nhiên từ 0-15 được thêm vào đó (xem fillArray () bên dưới). Chúng sẽ trông ngẫu nhiên, nhưng mỗi cái có một khóa tuần tự duy nhất. Để sắp xếp, chia cho 16 (trong C, >> 4 rất nhanh) và sau đó chỉ cần đặt số vào một mảng bằng cách sử dụng khóa kết quả làm chỉ mục. Một lượt và bạn đã hoàn thành. Trong thử nghiệm, tôi thấy quicksort chậm hơn 30 lần trên mười triệu số.

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;
}

Tất cả mọi thứ có một khóa duy nhất đều có thể được sắp xếp theo cách này - tất nhiên nếu bạn có bộ nhớ để lưu trữ. Ví dụ: nhiều cơ sở dữ liệu sử dụng id khách hàng số duy nhất - nếu danh sách đủ nhỏ / tuần tự, điều này có thể được giữ trong bộ nhớ. Hoặc một số cách khác để dịch một bản ghi thành một số duy nhất. Để biết thêm thông tin, hãy nghiên cứu Hash Sorts, vì đó là ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.