Em thì hiểu như vậy , không biết có đúng không :
iLo = integer Low, iHi = integer Hight --> tức là chỉ số trên và dưới của một đoạn phần tử trong mảng : Arr(iLo) : Arr(iHi)
* Vì đây là cách viết theo thuật toán đệ quy --> bắt buộc phải có 2 đối số iLo và iHi trong QuickSort
Vậy thôi ta tìm cách "quăng" biến ấy ra ngoài ở dạng Public hay gì đó đi
Nói chung là tôi không có khả năng sửa code, chỉ đứng trên QUAN ĐIỂM NGƯỜI DÙNG mà ĐÒI HỎI thôi
Ẹc... Ẹc...
Có thể về nguyên tắc của thuật toán nào đó thì phải bắt buộc như thế, nhưng với VBA của Excel thì không cần, vậy thì ta cứ giản thiểu biến một cách không cần thiết là được chứ nhỉ?
Tôi viết code 10 tháng trước. Có lúc nào tôi phàn nàn rằng không ai quan tâm, không ai dùng đâu. Tôi là ai mà có quyền ép mọi người dùng code của mình? Tôi không phàn nàn gì cả. Chỉ tới khi bạn so code của mình với code của huuthang_bd để rồi từ trên đỉnh cao chiến thắng diễu cợt vodoi2x
Thế cho nên đừng ai vỗ ngực xưng tên tôi hay và chê người ta ngớ ngẫn, mà hãy học thêm và biết chọn lọc tinh hoa của người khác mà ứng dụng vô công việc của mình. Bạn có giỏi thì cứ cắt bằng tay đi rồi nghiền nát, còn tôi thì dùng máy xay sinh tố vậy!
Bạn nghĩ là nó thừa hay bạn chắc chắn là nó thừa? Nếu chắc chắn thì vứt nó đi. Nếu sau đó code không chạy thì tự sửa.
Sức tôi có hạn thôi bạn ạ. Đâu có được như những vĩ nhân, siêu nhân, sư phụ GPE.
Tôi viết code 10 tháng trước. Có lúc nào tôi phàn nàn rằng không ai quan tâm, không ai dùng đâu. Tôi là ai mà có quyền ép mọi người dùng code của mình? Tôi không phàn nàn gì cả. Chỉ tới khi bạn so code của mình với code của huuthang_bd để rồi từ trên đỉnh cao chiến thắng diễu cợt vodoi2x
tôi mới đưa nó ra cho bạn xem. Thế thôi.
Tôi cũng đã trả lời câu mỉa mai "nó nằm tuốt luốt dưới đáy đại dương" ở chủ đề bên kia
Trước tiên, em xin nói rõ là em chẳng mỉa mai ai cả, chẳng qua là dùng từ cường điệu thôi, không có gì gọi là mỉa mai nhất là đối với bậc Thầy, bậc tiền bối cả.
Kế tiếp em nói thừa là vì sao, thay vì code thế này:
Mã:
Public Sub QuickSort1DArray(arr, [COLOR=#ff0000][B]iLo As Long, iHi As Long[/B][/COLOR], ByVal sortAtoZ As Boolean)
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (arr(Lo) > arr(Hi))
Else
DoChange = (arr(Lo) < arr(Hi))
End If
If DoChange Then
s = arr(Lo)
arr(Lo) = arr(Hi)
arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort1DArray arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Thì người viết code có thể thay đổi chút đỉnh cho người dùng cảm thấy tiện lợi hơn như thế này:
Mã:
Public Sub QuickSort1DArray(arr, ByVal sortAtoZ As Boolean)
[COLOR=#000000]
[/COLOR][COLOR=#ff0000][B]Dim iLo As Long, iHi As Long
iLo = LBound(Arr): iHi = UBound(Arr)[/B][/COLOR]
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (arr(Lo) > arr(Hi))
Else
DoChange = (arr(Lo) < arr(Hi))
End If
If DoChange Then
s = arr(Lo)
arr(Lo) = arr(Hi)
arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort1DArray arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Và cấu trúc đó, người dùng chỉ cần biết mảng đầu vào và chiều sort thôi:
QuickSort1DArray UserArr, True/False
Phải chăng là tiên lợi hơn chăng? Có ảnh hưởng gì đến code không?
Thầy góp ý cho em thì em rất vui lòng đón nhận vì kiến thức của Thầy rất vĩ đại, chẳng lẽ một góp ý cỏn con vậy mà Thầy lại khó chịu đến thế hay sao?
Bạn không phải đoán mò gì cả. Tôi là người có trách nhiệm nên thường giải thích rất kỹ. Cả ý nghĩa của đối số và chú thích cả những chỗ quan trọng trong code. Nếu bạn đọc code thì bạn sẽ thấy ngay trên đầu
Mã:
' Arr là mảng cần sắp xếp
' sortAtoZ xác định cách sắp xếp tăng hay giảm
' iLo là cận dưới của mảng Arr, iHi là cận trên của mảng Arr
Chuyện tác giả viết code như thế nào là chuyện của người ta. Nếu mình thấy dùng được thì dùng còn nếu thấy không hợp lý thì tự viết. Thế thôi. Ai đời lại có chuyện phỉ báng tác giả. Có thể người ta viết thế vì sức của người ta có thế, viết được như thế là cạn kiến thức rồi. Mình không vừa lòng thì vứt đi rồi tự viết. Mà có phỉ báng người ta thì trước tiên hãy tự viết, nếu được hãy phỉ báng.
Hix tại code bài #833 có đoạn này em không dịch được nên mới hỏi là " không biết có đúng không ?" chứ em có "đoán mò " theo ý hiểu của anh đâu :?
Mã:
Trích từ code bài #833
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laE maNng câEn saep xeep
' sortAtoZ xaec dinnh caech saep xeep tang hay giaNm
' iLo laE cânn dýoei cuNa maNng Arr, iHi laE cânn tren cuNa maNng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Trước tiên, em xin nói rõ là em chẳng mỉa mai ai cả, chẳng qua là dùng từ cường điệu thôi, không có gì gọi là mỉa mai nhất là đối với bậc Thầy, bậc tiền bối cả.
Kế tiếp em nói thừa là vì sao, thay vì code thế này:
Thì người viết code có thể thay đổi chút đỉnh cho người dùng cảm thấy tiện lợi hơn như thế này:
Mã:
Public Sub QuickSort1DArray(arr, ByVal sortAtoZ As Boolean)
[COLOR=#000000]
[/COLOR][COLOR=#ff0000][B]Dim iLo As Long, iHi As Long
iLo = LBound(Arr): iHi = UBound(Arr)[/B][/COLOR]
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (arr(Lo) > arr(Hi))
Else
DoChange = (arr(Lo) < arr(Hi))
End If
If DoChange Then
s = arr(Lo)
arr(Lo) = arr(Hi)
arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then [COLOR=#ff0000]QuickSort1DArray arr , sortAtoZ[/COLOR]
iLo = Lo
Loop Until Lo >= iHi
End Sub
Và cấu trúc đó, người dùng chỉ cần biết mảng đầu vào và chiều sort thôi:
QuickSort1DArray UserArr, True/False
Phải chăng là tiên lợi hơn chăng? Có ảnh hưởng gì đến code không?
Thầy góp ý cho em thì em rất vui lòng đón nhận vì kiến thức của Thầy rất vĩ đại, chẳng lẽ một góp ý cỏn con vậy mà Thầy lại khó chịu đến thế hay sao?
Hix tại code bài #833 có đoạn này em không dịch được nên mới hỏi là " không biết có đúng không ?" chứ em có "đoán mò " theo ý hiểu của anh đâu :?
Mã:
Public Sub QuickSort1DArray(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laE maNng câEn saep xeep
' sortAtoZ xaec dinnh caech saep xeep tang hay giaNm
' iLo laE cânn dýoei cuNa maNng Arr, iHi laE cânn tren cuNa maNng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Ơ lạ nhỉ?
Tôi có sửa gì đâu? Tự bạn đề nghị và tự bạn sửa. Tôi chỉ nói là: để biết code sau khi sửa có chạy không thì không cần phải hỏi ai cả. Thế thôi.
Hix cái vụ này là ý em muốn nhắn tới anh nghĩa với nội dung sau :
Nếu anh định viết theo kiểu dim iLo..... thì anh nên test trước khi post bài ,xem code có hoạt động không thôi !
Hix cái vụ này là ý em muốn nhắn tới anh nghĩa với nội dung sau :
Nếu anh định viết theo kiểu dim iLo..... thì anh nên test trước khi post bài ,xem code có hoạt động không thôi !
OK, có lẽ lần đầu tiên tôi thấy Sub chạy trong chính Sub đó nên tôi thắc mắc như thế, nếu đã đóng gói như là thư viện và chẳng thấy được mã nguồn thì thôi, còn đằng này thấy được mã nguồn và thắc mắc thì cũng là chuyện rất bình thường, nhưng qua đó sẽ được biết thêm về thủ tục này.
Như thế, tôi tự nhận khuyết điểm là "Có mắt mà không nhìn thấy Thái Sơn".
QuickSort là một trong những bài toán căn bản của lập trình.
Người nào học về thuật toán lập trình đều có học qua nó. Và bao nhiêu năm nay nó vẫn được viết với tham số như vậy, chả giảm thiểu được gì cả.
Lý do không thể dùng biến public/global (biến toàn cục):
- Về cách áp dụng: đây là hàm căn bản để dùng làm hàm thư viện. Theo nguyên tắc, hàm thư viện không được dùng biến toàn cục.
- Về cơ cấu code: đây là bài toán đệ quy, mà lại là đệ quy phi tuyến - tức là chính nó chẻ ra để gọi lại nó nhiều lần. Dùng biến toàn cục rất rắc rối và dễ sai.
Theo lệ thường, người ta chỉ dùng biến toàn cục khi sợ bị hết bộ nhớ cho ngăn xếp (stack). Nhưng đã sợ không đủ bộ nhớ thì đừng dùng hàm đệ quy nagy từ đầu.
- Về cơ cấu code: đây là bài toán đệ quy, mà lại là đệ quy phi tuyến - tức là chính nó chẻ ra để gọi lại nó nhiều lần. Dùng biến toàn cục rất rắc rối và dễ sai.
Private Sub QuickSort(Arr, iLo As Long, iHi As Long, ByVal sortAtoZ As Boolean)
' Arr laĚ maŇng câĚn săěp xęěp
' sortAtoZ xaěc điňnh caěch săěp xęěp tăng hay giaŇm
' iLo laĚ câňn dýőěi cuŇa maŇng Arr, iHi laĚ câňn tręn cuŇa maŇng Arr
Dim Lo As Long, Hi As Long, iMid, DoChange As Boolean, s
Do
Lo = iLo
Hi = iHi
iMid = Arr((Lo + Hi) \ 2)
Do
If sortAtoZ Then
Do While Arr(Lo) < iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) > iMid
Hi = Hi - 1
Loop
Else
Do While Arr(Lo) > iMid
Lo = Lo + 1
Loop
Do While Arr(Hi) < iMid
Hi = Hi - 1
Loop
End If
If Lo <= Hi Then
If sortAtoZ Then
DoChange = (Arr(Lo) > Arr(Hi))
Else
DoChange = (Arr(Lo) < Arr(Hi))
End If
If DoChange Then
s = Arr(Lo)
Arr(Lo) = Arr(Hi)
Arr(Hi) = s
End If
Lo = Lo + 1
Hi = Hi - 1
End If
Loop Until Lo > Hi
If Hi > iLo Then QuickSort Arr, iLo, Hi, sortAtoZ
iLo = Lo
Loop Until Lo >= iHi
End Sub
Public Sub QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean)
QuickSort Arr, LBound(Arr), UBound(Arr), sortAtoZ
End Sub
Tôi thấy là chả có lý do chính đáng nào để mà phải làm cho code nó phức tạp lên nên viết như vậy.
Nếu chuyện gõ thêm 2 thông số là việc làm hàng ngày, và mỗi ngày gõ 1000 lần thì tôi còn hiểu được đó là cực hình. Còn không thì không lý gì lại làm phức tạp code để chiều các vị lười. Vì chuyện gõ 2 thông số không phải là cực hình, cũng không là việc gây lúng túng cho người dùng. Gõ gõ thì có gì mà lúng túng.
Còn cứ muốn gõ ít thôi, và chỉ yêu sách duy nhất về chuyện gõ thêm thôi thì có khó gì?
code cho những người ngại gõ
Mã:
Public Sub QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean)
QuickSort Arr, LBound(Arr), UBound(Arr), sortAtoZ
End Sub
Gõ thì không ngại gì đâu Thầy ơi, nhưng với cách này (thêm 1 thủ tục như Thầy vừa làm) thì người dùng họ sẽ thấy "gần gũi" hơn. Giả sử em không biết gì về Ubound, về Lbound hay đại loại là không biết gì về mảng, em chỉ biết chép vào module và chạy code, thấy sướng quá, đem áp dụng luôn, vậy thì kiểu này QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean) người dùng sẽ sướng hơn đấy.
Vì kiến thức em chỉ học lõm tại diễn đàn này, không biết "quái" gì về "bài toán đệ quy hay đệ quy phi tuyến" vì thế làm sao mà biết được cách thức mà biến nó hoạt động như thế nào!
Và vì chả biết gì nên phát biểu linh tinh như thế đấy thôi (điếc không sợ súng là vậy đó Thầy ơi), thông cảm cho em.
Gõ thì không ngại gì đâu Thầy ơi, nhưng với cách này (thêm 1 thủ tục như Thầy vừa làm) thì người dùng họ sẽ thấy "gần gũi" hơn. Giả sử em không biết gì về Ubound, về Lbound hay đại loại là không biết gì về mảng, em chỉ biết chép vào module và chạy code, thấy sướng quá, đem áp dụng luôn, vậy thì kiểu này QuickSort1DArray(Arr, ByVal sortAtoZ As Boolean) người dùng sẽ sướng hơn đấy.
Vì kiến thức em chỉ học lõm tại diễn đàn này, không biết "quái" gì về "bài toán đệ quy hay đệ quy phi tuyến" vì thế làm sao mà biết được cách thức mà biến nó hoạt động như thế nào!
Và vì chả biết gì nên phát biểu linh tinh như thế đấy thôi (điếc không sợ súng là vậy đó Thầy ơi), thông cảm cho em.
...
Vì kiến thức em chỉ học lõm tại diễn đàn này, không biết "quái" gì về "bài toán đệ quy hay đệ quy phi tuyến" vì thế làm sao mà biết được cách thức mà biến nó hoạt động như thế nào!
...
Đệ quy trực tuyến là gọi lại theo đường thẳng, hàm gọi lại chính nó thẳng tuột một cách trực tiếp - ví dụ hàm tính giai thừa là tiêu biểu; dựa trên công thức n! = n*(n-1)!
Đệ quy phi tuyến không gọi trực tiếp theo đường thẳng mà có thể:
- Tán tuyến: chia ra nhiều nhánh, và lộn lại theo từng nhánh - tiêu biểu là bài quicksort
- Cách tuyến: rất rắc rối, hàm A gọi B, B gọi ngược lại A...
- Hỗn hợp đủ các kiểu trên.
Anh siwtom à!
Anh và em quen nhau trên diễn đàn này, thời gian tuy không dài nhưng cũng đủ để anh hiểu được con người em không phải thuộc loại thích bắt bẻ từng câu chữ.
Em tôn trọng anh vì kiến thức của anh... Em HỎI nhằm mục đích để HỌC. Em thấy "lúng túng" thì nói là "lúng túng"
Không ngờ chỉ câu hỏi nhỏ của em lại khiến anh mất bình tỉnh đến vậy
Thôi thì em xin lỗi... Hứa rằng sẽ không hỏi thêm gì nữa
Vậy đi nha!