Các lý do để tìm hiểu các thuật toán / cấu trúc dữ liệu khác nhau phục vụ cùng một mục đích là gì?


91

Tôi đã tự hỏi về câu hỏi này từ khi còn là sinh viên đại học. Đây là một câu hỏi chung nhưng tôi sẽ giải thích với các ví dụ dưới đây.

Tôi đã thấy rất nhiều thuật toán - ví dụ, đối với các vấn đề dòng chảy tối đa, tôi biết khoảng 3 thuật toán có thể giải quyết vấn đề: Ford-Fulkerson, Edmonds-Karp & Dinic, với Dinic có độ phức tạp tốt nhất.

Đối với các cấu trúc dữ liệu - ví dụ, heaps - có các heap nhị phân, heap nhị phân & heap Fibros, với heap Fibonacci có độ phức tạp tổng thể tốt nhất.

Điều khiến tôi bối rối là: có bất kỳ lý do tại sao chúng ta cần biết tất cả chúng? Tại sao không chỉ học và làm quen với sự phức tạp tốt nhất?

Tôi biết đó là điều tốt nhất nếu chúng ta biết tất cả, tôi chỉ muốn biết có bất kỳ lý do "hợp lệ hơn" nào không, như một số vấn đề / thuật toán chỉ có thể được giải quyết bằng cách sử dụng A chứ không phải B , v.v.


17
Như tôi luôn nói: những điều này (thường) không phải là "tốt nhất". Khi bạn xác định rõ ràng ý của bạn là "tốt hơn", câu trả lời sẽ trở nên rõ ràng.
Raphael

2
Đây là một câu hỏi hay, nhưng nó nói lên những gì tôi sẽ xem là lỗ hổng trong giáo dục của bạn mà bạn có thể xem xét để sửa chữa. Đó là kinh nghiệm thực tế, nếu bạn chưa thực sự viết các thuật toán này trong quá trình giáo dục của mình, bạn có thể cân nhắc viết chúng ngay bây giờ, tôi nghi ngờ câu trả lời cho câu hỏi này sẽ nhanh chóng trở nên rõ ràng khi bạn cố gắng tìm cách sử dụng chúng.
Sam

@Sam Từ kinh nghiệm của tôi, những gì tôi nghĩ là trong các bài giảng, hoặc một số sách giáo khoa, chúng có nhiều thông tin, giới thiệu nhiều thuật toán, phân tích, v.v., nhưng không có nhiều trường hợp thực tế hoặc các tình huống mẫu mà A sẽ vượt qua B. thể loại thuật toán từ A đến Z và một số vấn đề về bài tập về nhà, nhưng với tôi tất cả chúng chỉ có thể giải quyết bằng A, hoặc chỉ bằng Z, v.v., do đó, câu hỏi được đặt ra.
shole

5
Nếu bạn khăng khăng bỏ qua lợi ích học thuật sang một bên, lý do thực tế tốt nhất để học ít hơn các thuật toán tối ưu là để bạn có thể nhận ra chúng cho những gì chúng là và tối ưu hóa chúng bằng cách tái cấu trúc thành các thuật toán tối ưu. Bạn không thể nâng cấp cung và mũi tên thành súng nếu bạn không biết cung và mũi tên là gì.
candied_orange

1
Chúng tôi thực sự đã đề xuất một trang web StackExchange để đặc biệt giúp đỡ với các câu hỏi giáo dục CS như thế này. Hãy đến ủng hộ chúng tôi tại đây: area51.stackexchange.com/proposeals/92460/ trên
vk2015

Câu trả lời:


121

Có một cuốn sách giáo khoa đang chờ để được viết vào một lúc nào đó, với tiêu đề làm việc Cấu trúc dữ liệu, Thuật toán và Trao đổi . Hầu như mọi thuật toán hoặc cấu trúc dữ liệu mà bạn có khả năng học ở cấp đại học đều có một số tính năng giúp nó tốt hơn cho một số ứng dụng so với các ứng dụng khác.

Hãy lấy việc sắp xếp làm ví dụ, vì mọi người đều quen thuộc với các thuật toán sắp xếp tiêu chuẩn.

Trước hết, sự phức tạp không phải là mối quan tâm duy nhất. Trong thực tế, các yếu tố không đổi quan trọng, đó là lý do tại sao (nói) sắp xếp nhanh có xu hướng được sử dụng nhiều hơn sắp xếp heap mặc dù sắp xếp nhanh có độ phức tạp trong trường hợp xấu nhất.

Thứ hai, luôn có cơ hội bạn thấy mình trong tình huống bạn đang lập trình dưới những ràng buộc lạ lùng. Tôi đã từng phải thực hiện trích xuất định lượng từ bộ sưu tập mẫu có kích thước khiêm tốn (1000 hoặc hơn) nhanh nhất có thể, nhưng đó là trên một vi điều khiển nhỏ có rất ít bộ nhớ đọc ghi dự phòng, do đó loại trừ hầu hết sắp xếp các thuật toán. Shell sort là sự đánh đổi tốt nhất, vì nó là bậc hai và không cần thêm bộ nhớ.O(nlogn)

Trong các trường hợp khác, các ý tưởng từ thuật toán hoặc cấu trúc dữ liệu có thể được áp dụng cho một vấn đề có mục đích đặc biệt. Sắp xếp bong bóng dường như luôn chậm hơn so với sắp xếp chèn trên phần cứng thực, nhưng ý tưởng thực hiện vượt qua bong bóng đôi khi chính xác là những gì bạn cần.

Ví dụ, hãy xem xét một số loại hình ảnh 3D hoặc trò chơi video trên thẻ video hiện đại, trong đó bạn muốn vẽ các vật thể theo thứ tự từ máy ảnh gần nhất đến máy ảnh xa nhất vì lý do hiệu suất, nhưng nếu bạn không nhận được đơn đặt hàng chính xác, phần cứng sẽ xử lý nó. Nếu bạn di chuyển xung quanh môi trường 3D, thứ tự tương đối của các đối tượng sẽ không thay đổi nhiều giữa các khung, do đó, việc thực hiện một bong bóng vượt qua mọi khung hình có thể là một sự đánh đổi hợp lý. (Công cụ nguồn của Valve thực hiện điều này cho các hiệu ứng hạt.)

Có sự tồn tại, đồng thời, cục bộ bộ đệm, khả năng mở rộng trên một cụm / đám mây và một loạt các lý do có thể khác tại sao một cấu trúc dữ liệu hoặc thuật toán có thể phù hợp hơn so với một cấu trúc tính toán tương tự cho các hoạt động mà bạn quan tâm.

Như đã nói, điều đó không có nghĩa là bạn nên ghi nhớ một loạt các thuật toán và cấu trúc dữ liệu chỉ trong trường hợp. Hầu hết các trận chiến đều nhận ra rằng có một sự đánh đổi sẽ được khai thác ngay từ đầu và biết phải tìm ở đâu nếu bạn nghĩ có thể có thứ gì đó phù hợp.


7
Câu trả lời tuyệt vời với những ví dụ tuyệt vời! Thậm chí không biết bong bóng có công dụng thực tế trong thế giới thực ...
shole 17/2/2016

1
@shole Tôi không có nhiều kinh nghiệm trong kinh doanh trò chơi, nhưng tất cả những điều trên đều quan trọng ở các mức độ khác nhau. (Rõ ràng, các loại thuật toán, cấu trúc dữ liệu và toán học mà bạn cần cho các trò chơi có thể khác với các thuật toán cần thiết cho cơ sở dữ liệu hoặc tin sinh học hoặc những gì có bạn.) Nếu tôi là bạn, tôi sẽ đến đây và bắt đầu xem: handmade. org Ngoài ra, nó có thể đáng để ẩn trên gamedev.stackexchange.com
Bút danh

1
Hiệu quả của bộ nhớ cache là một yếu tố lớn được nghiên cứu kỹ lưỡng (google "tường nhớ").
Raphael

6
Cẩn thận, Quicksort trung bình nhanh hơn nhiều so với Heapsort, nhưng Heapsort thì nhất quán hơn (phương sai của thời gian chạy là ít hơn, và trường hợp xấu nhất thì tốt hơn nhiều). Và việc Heapsort nhảy xung quanh trong mảng so với quét tuyến tính của Quicksort từ trái và phải tạo ra sự khác biệt lớn khi bộ đệm / phân trang xuất hiện.
vonbrand

1
@shole Loại phát triển trò chơi nào bạn quan tâm? Có ít nhất hai trường con rất khác nhau, đồ họa 3D và lối chơi (bao gồm cả AI). Tôi chỉ có kinh nghiệm với đồ họa, nhưng tôi có thể nói rằng cấu trúc dữ liệu và toán học là cực kỳ quan trọng trong đồ họa, và các thuật toán cũng ở mức độ thấp hơn. Nếu bạn đang sử dụng một công cụ thì hầu hết các công cụ này tất nhiên sẽ được quan tâm, nhưng bạn vẫn nên hiểu toán học cơ bản của hình học 3D.
vườn

51

Bên cạnh thực tế là có vô số biện pháp chi phí (thời gian chạy, sử dụng bộ nhớ, lỗi bộ nhớ cache, dự đoán sai chi nhánh, độ phức tạp triển khai, tính khả thi của xác minh ...) trên vô số mô hình máy (TM, RAM, PRAM, ...) , trường hợp trung bình so với trường hợp xấu nhất cũng như các cân nhắc khấu hao để cân nhắc với nhau, thường cũng có những khác biệt về chức năng vượt quá phạm vi của đặc tả sách giáo khoa cơ bản.

Vài ví dụ:

  • Mergesort ổn định ở nơi Quicksort không có.
  • Cây tìm kiếm nhị phân cung cấp cho bạn lần lặp theo thứ tự, hashtables không.
  • Bellman-Ford có thể đối phó với trọng lượng cạnh âm, Dijkstra không thể.

Ngoài ra còn có những cân nhắc về mô phạm để thực hiện:

  • Làm thế nào dễ dàng để hiểu một giải pháp liên quan nhiều hơn trước khi những giải pháp đơn giản hơn? (Cây AVL (và phân tích của chúng) không có BST; Dinic không có Ford-Fulkerson; ...)
  • Bạn có thấy các nguyên tắc và mô hình tương tự khi bạn chỉ tiếp xúc với một giải pháp cho mỗi vấn đề so với việc tiếp xúc với nhiều giải pháp không?
  • Liệu giải thích cho chỉ một giải pháp cho mỗi vấn đề cung cấp đủ đào tạo (hướng tới làm chủ)?
  • Bạn có nên biết chiều rộng của các giải pháp đã được tìm thấy (để ngăn bạn phát minh lại bánh xe hơn và hơn)?
  • Khi tiếp xúc với chỉ một giải pháp cho mỗi vấn đề, bạn sẽ hiểu các giải pháp khác mà bạn tìm thấy trong tự nhiên (giả sử trong thư viện lập trình trong thế giới thực)?

  1. Đây là điều chúng tôi thấy rất nhiều từ các loại lập trình viên không có hộp công cụ CS phong phú theo ý của họ.

4
+1 để bao gồm các lý do mô phạm! Liên quan đến một số lý do (đặc biệt là thứ hai và thứ ba), xem cách thuật toán và cấu trúc dữ liệu được phát triển và tối ưu hóa dạy các kỹ thuật phát triển và tối ưu hóa và hiểu về sự đánh đổi (học không chỉ "cái gì" mà còn "làm thế nào" và "tại sao" ).
Paul A. Clayton

2
Một xem xét thêm là phân tích các lựa chọn thay thế khác nhau cung cấp các ví dụ về các công cụ hữu ích để phân tích các thuật toán mới cho các cài đặt có lẽ bất thường.
vonbrand

1
Điểm tốt, @vonbrand. Phân tích độ phức tạp khấu hao được phát minh để hiểu hành vi của cây splay, nhưng cây splay hiếm khi được sử dụng trong thực tế. Chà, dù sao cũng không chơi cây như đã xuất bản. Nhân Windows NT nổi tiếng sử dụng cây splay để thực hiện các bản đồ bộ nhớ ảo, nhưng nó không sắp xếp lại trên mỗi lần tra cứu.
Bút danh

1
@vonbrand Vâng. Tôi sẽ hiểu làm thế nào mà ai đó chủ yếu quan tâm đến kích thước hộp công cụ trên một lớp thuật toán sẽ chế giễu lý do đó.
Raphael

7

Trong thế giới thực , đến một lúc nào đó bạn có khả năng đang làm việc trên phần mềm đã được viết bởi một nhóm người khác. Một số phần mềm này sẽ được viết trước khi bạn được sinh ra!

Vì vậy, để hiểu các thuật toán / cấu trúc dữ liệu được sử dụng, sẽ rất hữu ích khi biết một số lượng lớn thuật toán / cấu trúc dữ liệu, bao gồm các tùy chọn không còn được xem là trạng thái của nghệ thuật.

Bạn cũng sẽ phải làm việc trên các thuật toán không chuẩn và chỉ được sử dụng trong ứng dụng bạn đang làm việc. Khi bạn phải cải thiện các thuật toán này, bạn sẽ thấy rằng bộ não của bạn đã được lấp đầy bằng các phương pháp hữu ích để cải thiện thuật toán, vì bạn đã nghiên cứu cách người khác cải thiện thuật toán.

Đây là những gì khiến ai đó đã nghiên cứu khoa học máy tính khác với một người vừa mới học cách lập trình. Trong hầu hết các công việc tôi đã làm, đã có thời gian khi nghiên cứu về khoa học máy tính, tôi có thể giải quyết một vấn đề mà một người học được từ sách của lập trình viên không thể làm được, nhưng 95% thời gian tôi thấy rằng việc học khoa học máy tính không cho tôi lợi thế hơn các lập trình viên có kinh nghiệm khác .


trừ khi 95% những điều bạn đang cố gắng giải quyết có liên quan đến Machine learning. Tôi không thể thấy làm thế nào lập trình viên bình thường thậm chí có thể có cơ hội đúng để thử bất kỳ vấn đề nào gặp phải bởi các vấn đề ML thực sự.
Pinocchio

3
Mục tiêu: có được một công việc với tỷ lệ tốt hơn 5%.
Raphael

Hãy nhớ rằng nghiên cứu CS là một cách tuyệt vời để thu thập kiến ​​thức về thuật toán và cấu trúc dữ liệu. Viết mã nghề nghiệp tốt nhất - cho các lập trình viên.
greybeard

5

Nhiều người đã đề cập đúng rằng thường không có một thuật toán tốt nhất - nó phụ thuộc vào tình huống.

Cũng có khả năng một ngày nào đó bạn sẽ gặp một tình huống lạ lẫm. Bạn càng biết nhiều thuật toán, bạn càng có nhiều cơ hội biết một giải pháp gần như là một giải pháp mà bạn có thể sử dụng làm cơ sở.


5
Câu trả lời này chỉ lặp lại điểm từ những người lớn tuổi hơn.
Raphael

1

Rất nhiều câu trả lời hay, chỉ là thứ tôi nghĩ còn thiếu, mặc dù câu trả lời của Raphael phần nào đề cập đến điều này.

Dễ thực hiện cũng là một cái gì đó để xem xét.
Điều đó thường không phải là vấn đề với các thuật toán sắp xếp, bởi vì hầu hết các nền tảng / ngôn ngữ đã được triển khai (và thường tốt hơn những gì bạn có thể làm), nhưng các thuật toán khác thường hơn có thể không khả dụng.
Tùy thuộc vào vấn đề của bạn, bạn có thể không cần thuật toán tốt nhất tuyệt đối nếu thời gian thực hiện là 1 ngày so với 2 tuần.

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.