Thực hành tốt để viết thuật toán


22

Đây là về cách hiệu quả chúng ta có thể thể hiện một thuật toán trong tầm tay. Tôi cần điều này cho giảng dạy đại học của tôi.

Tôi hiểu không có cách nào như cách viết mã giả. Các tác giả khác nhau theo các quy ước khác nhau.

Sẽ rất hữu ích nếu mọi người ở đây chỉ ra, cách họ theo dõi và suy nghĩ tốt nhất.

Có cuốn sách nào đề cập đến vấn đề này một cách chi tiết không?


9
"tốt nhất" là rất chủ quan, tôi nghĩ bạn nên sửa đổi tiêu đề và thay vì yêu cầu "tốt nhất" yêu cầu những gì mọi người làm trong thực tế. Có thể một cái gì đó như "làm thế nào để trình bày các thuật toán" hoặc "thực hành tốt để trình bày các thuật toán". Bạn cũng có thể muốn cụ thể hơn kể từ khi trình bày các thuật toán: 1. cho học sinh trong lớp dưới đại học 2. trong sách giáo khoa 3. trong một bài báo hội thảo là những nhiệm vụ rất khác nhau.
Kaveh

1
Bạn cũng có thể muốn kiểm tra các phần có liên quan của Viết toán học của Knuth, Larrabee và Roberts.
Kaveh

Câu trả lời:


26

Viết mã giả giống như viết mã: Việc bạn tuân theo tiêu chuẩn nào không quan trọng, miễn là bạn (và những người bạn viết cùng) thực sự tuân theo một số tiêu chuẩn.

Nhưng đối với hồ sơ, đây là tiêu chuẩn bình dị mà tôi sử dụng trong các bài giảng, tài liệu nghiên cứu và cuốn sách sắp tới.

  • Sử dụng cú pháp mệnh lệnh chuẩn để truy cập luồng điều khiển và bộ nhớ - if, while, for, return, mảng [index], function (argument). Đánh vần "khác nếu".

    • Nhưng sử dụng thay vì hoặcfield(record)record.fieldrecord->field
  • Sử dụng ký hiệu toán học tiêu chuẩn cho toán học - Viết thay vì , thay vì , thay vì , thay vì , thay vì , thay vì , thay vì , v.v.xyx*yamodba%b¬ p sts <= t¬p!p pixsqrt(x)πPIMAX_INT

    • Nhưng sử dụng để gán, để tránh sự cố.xy==

    • Nhưng tránh ký hiệu (và mã giả!) Hoàn toàn nếu tiếng Anh rõ ràng hơn.

      • Đối xứng, tránh tiếng Anh nếu ký hiệu rõ ràng hơn!
  • Giảm thiểu đường cú pháp - Chỉ ra cấu trúc khối bằng cách thụt đầu dòng nhất quán (à la Python). Bỏ qua các từ khóa có đường như "bắt đầu / kết thúc" hoặc "do / od" hoặc "fi". Bỏ qua số dòng. Đừng không nhấn mạnh các từ khóa như "cho" hoặc "trong khi" hoặc "nếu" bằng cách thiết lập chúng trong một khác nhau typefacehoặc phong cách . Không bao giờ. Chỉ không.

    • Nhưng các tên và hằng số thuật toán sắp chữ trong \ textc {Small Caps}, tên biến in nghiêng và chuỗi ký tự bằng sans serif.

    • Nhưng thêm một lượng nhỏ không gian "thở" dọc ( \\[0.5ex]) giữa các đoạn mã có ý nghĩa.

  • Đừng chỉ định chi tiết không quan trọng. Nếu việc bạn truy cập các đỉnh không quan trọng, chỉ cần nói "cho tất cả các đỉnh".

Ví dụ, đây là một công thức đệ quy của thuật toán cây bao trùm tối thiểu của Borůvka . Trước đây tôi đã xác định là đồ thị thu được từ bằng cách ký hợp đồng tất cả các cạnh trong tập và Flatten là một chương trình con loại bỏ các vòng lặp và các cạnh song song.G LG/LGL

Thuật toán của Borůvka

Tôi sử dụng algorithmmôi trường LaTeX nhẹ của riêng tôi để gõ mã giả. (Đây chỉ là một tabbingmôi trường bên trong \fbox.) Đây là mã nguồn của tôi cho thuật toán của Borůvka:

\begin{algorithm}
	\textul{$\textsc{Borůvka}(G)$:}\+
\\	if $G$ has no edges\+
\\		return $\varnothing$\-
\\[0.5ex]
	$L \gets \varnothing$
\\	for each vertex $v$ of $G$\+
\\		add the lightest edge incident to $v$ to $L$\-
\\[0.5ex]
	return $L \cup \textsc{Borůvka}(\textsc{Flatten}(G / L))$
\end{algorithm}

thú vị là bạn sử dụng trường (bản ghi) thay vì bản ghi [trường]. Tôi tưởng tượng đây là " là tọa độ của " của thế giới? j t h vfj(v)jthv
Suresh Venkat

@SureshVenkat: Đó là cách bạn thường làm điều đó trong các ngôn ngữ chức năng và cũng là ký hiệu trong TAoCP. (Rõ ràng, tôi không thể biết đó là lý do tại sao J ff E sử dụng ký hiệu này.)
Radu GRIGore

5
Lý do chính để cẩn thận với mã giả là dễ bị nhầm lẫn về thuật toán nên điều quan trọng là phải nhấn mạnh một số điều. Ví dụ của Jeff ở trên cho Boruvka minh họa điều này. Trong mã L đang được coi là một bộ. Một uv cạnh có thể là sự cố cạnh nhẹ nhất đối với bạn cũng như v vì vậy nó được thêm hai lần trong vòng lặp nhưng không thành vấn đề nếu bạn nghĩ L là một tập hợp. Tuy nhiên, điều này không rõ ràng và một số người thực hiện điều này có thể dễ dàng tăng gấp ba nếu họ thực hiện L như một danh sách.
Chandra Chekuri

2
@ChandraChekuri: Có, việc triển khai các bộ không chính xác có thể gây ra sự cố trong các thuật toán thao tác các bộ.
Jeffε

1
@SureshVenkat: Ồ, cái đó. Không, tôi không thể chịu đựng được. Từ khóa táo bạo làm cho bé Jesus khóc. Dijkstra nên mất giải thưởng Turing vì đã giới thiệu quy ước đánh máy có thể thực hiện được.
Jeffε

11

Tôi có xu hướng sử dụng một cái gì đó tương tự cú pháp Python. Python đủ gần với mã giả, trong một số trường hợp, mã giả của tôi có thể trở thành mã làm việc thực tế.


Tôi cũng vậy, nhưng trong Ruby. Với các github, bạn có thể dễ dàng chia sẻ các đoạn mã thực thi để chúng chơi. gist.github.com/chadbrewbaker/7202412
Chad Brewbaker 17/11/13

Python tuy nhiên không tốt để biểu diễn đại số tuyến tính. Octave là một sự phù hợp tốt hơn tôi nghĩ trong trường hợp này (gần với mã giả).
gabious

3

Nếu bạn muốn có mã xác định (nghĩa là ít hoặc không có toán học, gần với lập trình thực), bạn có thể muốn xem xét để có mã thực sự biên dịch. Điều này có một số lợi thế:

  • Bạn nhận được cú pháp tô sáng ở khắp mọi nơi.
  • Trình biên dịch kiểm tra cú pháp cho bạn và thực thi tính nhất quán.
  • Bạn có thể kiểm tra đơn vị triển khai của mình để cải thiện chất lượng mã.
  • Bạn có thể chạy thuật toán và so sánh thời gian chạy đo được với các phân tích (do đó thúc đẩy các kỹ thuật phân tích nâng cao).

Một giáo sư tại trường đại học của tôi làm điều này trong khóa học thuật toán của mình. Ngôn ngữ anh ấy chọn là Modula. Tôi không nghĩ rằng sự lựa chọn đặc biệt của các vấn đề ngôn ngữ, mặc dù. Chỉ cần bám vào một (mỗi mô hình) phù hợp nhất với mức độ trừu tượng của bạn.


"Chỉ cần bám vào một (theo mô hình) phù hợp nhất với mức độ trừu tượng của bạn." Tôi nghĩ rằng đây là một lời khuyên tuyệt vời để tìm một giải pháp thay thế cho mã giả. Có rất nhiều ngôn ngữ và hầu như luôn có ít nhất một ngôn ngữ nhắm đến một cú pháp đơn giản cho mô hình cụ thể: Ada cho thiết kế đồng thời, Octave cho đại số tuyến tính, Python cho thủ tục, NetLogo cho các hệ thống đa tác nhân, Prolog cho logic, CLIPS cho lập trình dựa trên quy tắc, v.v.
gabious

@gabious Nếu bạn có thể đọc được mã trừu tượng - hãy tìm nó. Thật không may, tôi nghi ngờ rằng điều này sẽ khiến bạn sử dụng ít nhất ba ngôn ngữ trong bất kỳ khối lượng công việc lớn hơn; điều đó cũng thật đáng tiếc
Raphael

tất nhiên tôi đồng ý với mã lớn hơn không có ngôn ngữ, nhưng đối với các thuật toán nhỏ, cốt lõi, thường có thể tìm thấy một ngôn ngữ rất gần với mã giả.
gabious
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.