Tôi đang làm việc theo cách của mình thông qua cuốn sách Giới thiệu về thuật toán, ấn bản thứ 3. Một trong những điều đầu tiên được giải thích là loại sắp xếp. Trên trang 18 có một số mã giả:Không thể sắp xếp chèn từ phần giới thiệu đến thuật toán thứ 3 ed. đúng. Sai lầm suy nghĩ của tôi ở đâu?
A = {5, 2, 4, 6, 1, 3};
Nó nói rằng mã giả được sử dụng để nó dễ dàng dịch sang bất kỳ loại ngôn ngữ nào (C, C++, Java, chúng không đề cập đến, nhưng tôi cũng đoán C#). Kể từ khi tôi chương trình trong C#, tôi dịch nó trong LinqPad.
int[] a = { 5, 2, 4, 6, 1, 3 };
for (var j = 1; j < a.Length; j++)
{
var key = a[j];
var i = j - 1;
while(i > 0 && a[i] > key)
{
a[i + 1] = a[i];
i--;
}
a[i + 1] = key;
}
a.Dump();
Có thể bạn sẽ hỏi, tại sao j bắt đầu ở mức 1 khi nói rõ 2? Trong cuốn sách, mảng có một chỉ số bắt đầu từ 1. Và có, tôi bây giờ tôi có lẽ nên đã cập nhật tất cả các [i - 1]
và [i + i]
là tốt.
Dù sao, sau khi tôi đã hoàn tất, tôi chạy mã và nhận thấy rằng nó không thực sự sắp xếp chính xác. Đầu ra là { 5, 1, 2, 3, 4, 6 }
. Đã muộn và đáng lẽ phải dừng lại, nhưng tôi đã phải vật lộn để làm cho mã đúng. Tôi đã làm tất cả mọi thứ, thậm chí lấy mã giả như là từ cuốn sách (bắt đầu từ 2). Vẫn không có đầu ra chính xác.
tôi đã liên lạc với một trong những giáo sư của cuốn sách, và anh gửi cho tôi mã cho loại chèn, trong C:
void insertion_sort(int *A, int n) {
for (int j = 2; j <= n; j++) {
int key = A[j];
int i = j-1;
while (i > 0 && A[i] > key) {
A[i+1] = A[i];
i--;
}
A[i+1] = key;
}
}
dịch trong C#:
int [] a = {5 , 2, 4, 6, 1, 3};
for (var j = 2; j <= a.Length; j++)
{
var key = a[j];
var i = j - 1;
while(i > 0 && a[i] > key)
{
a[i + 1] = a[i];
i--;
}
a[i + 1] = key;
}
Tôi nhận được một mảng ngoài giới hạn. Được rồi, có thể:
int [] a = {5, 2, 4, 6, 1, 3};
for (var j = 2; j <= a.Length - 1; j++)
{
var key = a[j];
var i = j - 1;
while(i > 0 && a[i] > key)
{
a[i + 1] = a[i];
i--;
}
a[i + 1] = key;
}
Output: {5, 1, 2, 3, 4, 6}
Tôi đang nghĩ, điều này có thể không chính xác. Mã giả nói 2 đến mảng.Length. Có phải là 2 < mảng.Length, hoặc 2 < = array.Length? Chuyện gì đang xảy ra ở đây?
Cá nhân tôi nghĩ rằng đó là do thuộc tính 0 > 0
trong vòng lặp while. Nó thực sự rơi ngắn một lần mỗi lần.
lời giải thích của tôi (từ email của tôi gửi đến các giáo sư, để lười biếng để gõ nó trên tất cả):
Lý do tại sao vòng lặp vẫn kết thúc với { 5, 1, 2, 3, 4, 6 }
là vì i > 0
vị. Mỗi lần trong vòng lặp while bạn trừ 1 của i (i--
). Điều này cuối cùng sẽ dẫn đến 0 > 0
kết thúc sai (chỉ 0 == 0
sẽ trả về true), nhưng đây là khi vòng lặp vẫn cần chạy thêm một lần nữa. Nó liên tục rơi một đoạn ngắn. Nó sẽ đi làm trong khi vòng lặp 1 thêm thời gian để sắp xếp đúng cách.
Một lời giải thích:
Khi j bắt đầu với 2, phím == 4, i == 1 và a [i] == 2. Vòng lặp while sẽ không chạy trong trường hợp này vì 2> 0 nhưng 2 không lớn hơn 4.
j == 3, key == 6, i == 2, a[i] == 4
Trong khi vòng lặp sẽ không chạy vì 4 là không lớn hơn 6
j == 4, key == 1, i == 3, a[i] == 6
Trong khi vòng lặp chạy thời gian này:
a[i + 1] = a[i] -> a[4] = a[3] -> { 5, 2, 4, 6, 6, 3 } i-- -> i == 2
Một lần nữa trong khi vòng lặp vì 2> 0 và 4> 1
a[i + 1] = a[i] -> a[3] = a[2] -> { 5, 2, 4, 4, 6, 3 } i-- -> i == 1
Một lần nữa trong khi vòng lặp vì 1> 0 và 2> 1
a[i + 1] = a[i] -> a[2] = a[1] -> { 5, 2, 2, 4, 6, 3 } i-- -> i == 0
Và đây là nơi mà nó đi (theo ý kiến của tôi) sai. Bây giờ tôi bằng 0, nhưng vòng lặp while nên chạy thêm một lần nữa để lấy 5 ra khỏi vị trí thứ 0.
Giáo sư đảm bảo với tôi rằng anh ấy đúng, nhưng tôi không thể có được kết quả đúng. Tư duy của tôi đi sai ở đâu?
Mảng trong mã C mà giáo sư gửi cho tôi thực sự bắt đầu bằng chỉ mục 1. Tôi không biết điều này và kiểm tra mảng C tôi thấy tất cả bắt đầu bằng 0. Có , sau đó mã C không tạo ra kết quả chính xác. Vị giáo sư đã giải thích điều này với tôi và các mảnh bây giờ rơi vào vị trí của nó.
Mọi ngôn ngữ lập trình Tôi biết chỉ mục mảng từ 0. Tôi nghĩ MATLAB và R có thể là ngoại lệ, nhưng chúng không phải là ngôn ngữ lập trình thực. :-) –