Làm thế nào để thực hiện một hàng đợi với ba ngăn xếp?


136

Tôi đã bắt gặp câu hỏi này trong một cuốn sách thuật toán ( Thuật toán, Phiên bản thứ 4 của Robert Sedgewick và Kevin Wayne).

Xếp hàng với ba ngăn xếp. Thực hiện một hàng đợi với ba ngăn xếp sao cho mỗi hoạt động hàng đợi có số lượng hoạt động ngăn xếp không đổi (trường hợp xấu nhất). Cảnh báo: độ khó cao.

Tôi biết cách sắp xếp hàng với 2 ngăn xếp nhưng tôi không thể tìm ra giải pháp với 3 ngăn xếp. Bất kỳ ý tưởng ?

(oh và, đây không phải là bài tập về nhà :))


30
Tôi đoán đó là một biến thể của Tháp Hà Nội .
Gumbo

14
@Jason: Câu hỏi đó không phải là một bản sao, vì nó yêu cầu thời gian khấu hao O (1) trong khi câu hỏi này yêu cầu trường hợp xấu nhất O (1) cho mỗi thao tác. Giải pháp hai ngăn xếp của DuoSRX đã là thời gian khấu hao O (1) cho mỗi thao tác.
interjay

15
Tác giả chắc chắn không đùa khi nói "Cảnh báo: độ khó cao."
BoltClock

9
@Gumbo thật không may sự phức tạp về thời gian của Tháp Hà Nội không nơi nào gần với thời gian không đổi!
Phổ

12
Lưu ý: Câu hỏi trong văn bản đã được cập nhật vào đây: Thực hiện một hàng đợi với số lượng ngăn xếp không đổi [không phải "3"] để mỗi hoạt động hàng đợi có một số lượng hoạt động ngăn xếp không đổi (trường hợp xấu nhất). Cảnh báo: độ khó cao. ( alss4.cs.princeton.edu/13stacks - Mục 1.3.43). Có vẻ như Giáo sư Sedgewick đã thừa nhận thách thức ban đầu.
Mark Peters

Câu trả lời:


44

TÓM LƯỢC

  • Thuật toán O (1) được biết đến với 6 ngăn xếp
  • Thuật toán O (1) được biết đến với 3 ngăn xếp, nhưng sử dụng đánh giá lười biếng trong thực tế tương ứng với việc có thêm cấu trúc dữ liệu bên trong, vì vậy nó không tạo thành một giải pháp
  • Những người gần Sedgewick đã xác nhận rằng họ không biết về giải pháp 3 ngăn xếp trong tất cả các ràng buộc của câu hỏi ban đầu

CHI TIẾT

Có hai triển khai đằng sau liên kết này: http://www.eecs.usma.edu/webs/people/okasaki/jfp95/index.html

Một trong số đó là O (1) với ba ngăn xếp NHƯNG nó sử dụng thực thi lười biếng, trong thực tế tạo ra các cấu trúc dữ liệu trung gian bổ sung (đóng).

Một trong số đó là O (1) nhưng sử dụng ngăn xếp SIX. Tuy nhiên, nó hoạt động mà không lười thực hiện.

CẬP NHẬT: Bài viết của Okasaki ở đây: http://www.eecs.usma.edu/webs/people/okasaki/jfp95.ps và có vẻ như anh ta thực sự chỉ sử dụng 2 ngăn xếp cho phiên bản O (1) có đánh giá lười biếng. Vấn đề là nó thực sự dựa trên đánh giá lười biếng. Câu hỏi là nếu nó có thể được dịch sang thuật toán 3 ngăn xếp mà không lười đánh giá.

CẬP NHẬT: Một thuật toán liên quan khác được mô tả trong bài báo "Ngăn xếp so với Deques" của Holger Petersen, được xuất bản trong Hội nghị thường niên lần thứ 7 về Điện toán và Kết hợp. Bạn có thể tìm thấy bài viết từ Google Sách. Kiểm tra trang 225-226. Nhưng thuật toán không thực sự là mô phỏng thời gian thực, đó là mô phỏng thời gian tuyến tính của hàng đợi hai đầu trên ba ngăn xếp.

gusbro: "Như @Leonel đã nói cách đây vài ngày, tôi nghĩ sẽ công bằng khi kiểm tra với Giáo sư Sedgewick nếu anh ta biết một giải pháp hoặc có một số sai lầm. Vì vậy, tôi đã viết thư cho anh ta. bản thân anh ấy nhưng từ một đồng nghiệp tại Princeton) vì vậy tôi muốn chia sẻ với tất cả các bạn. Về cơ bản, anh ấy nói rằng anh ấy không biết về thuật toán sử dụng ba ngăn xếp VÀ các ràng buộc khác được áp đặt (như không sử dụng đánh giá lười biếng). 6 ngăn xếp như chúng ta đã biết khi nhìn vào các câu trả lời ở đây. Vì vậy, tôi đoán câu hỏi vẫn đang mở để tìm một thuật toán (hoặc chứng minh không thể tìm thấy một thuật toán). "


Tôi chỉ bay qua các giấy tờ và chương trình trong liên kết của bạn. Nhưng nếu tôi thấy đúng họ không sử dụng ngăn xếp, họ sử dụng danh sách làm loại cơ bản. Và đặc biệt. trong các danh sách này được xây dựng với tiêu đề và phần còn lại, vì vậy về cơ bản nó trông giống với giải pháp của tôi (và tôi nghĩ là không đúng).
flolo

1
Xin chào, việc triển khai là trong một ngôn ngữ chức năng nơi các danh sách tương ứng với các ngăn xếp miễn là các con trỏ không được chia sẻ, và chúng thì không; phiên bản sáu ngăn xếp có thể được thực hiện bằng cách sử dụng sáu ngăn xếp "đơn giản". Vấn đề với phiên bản hai / ba ngăn xếp là nó sử dụng các cấu trúc dữ liệu ẩn (các bao đóng).
Antti Huima

Bạn có chắc chắn giải pháp sáu ngăn không chia sẻ con trỏ? Trong rotateđó, có vẻ như frontdanh sách được gán cho cả hai oldfrontfsau đó chúng được sửa đổi riêng.
interjay

14
Tài liệu nguồn tại alss4.cs.princeton.edu/13stacks đã được thay đổi: 43. Thực hiện một hàng đợi với số lượng ngăn xếp [không phải là "3" không đổi để mỗi hoạt động hàng đợi có số ngăn xếp (trường hợp xấu nhất) không đổi hoạt động. Cảnh báo: độ khó cao. Tiêu đề của thử thách vẫn nói "Hàng đợi với ba ngăn xếp" tuy nhiên :-).
Mark Peters

3
@AnttiHuima Liên kết sáu ngăn xếp đã chết, bạn có biết điều này có tồn tại ở đâu đó không?
Quentin Pradet

12

Ok, điều này thực sự khó, và giải pháp duy nhất tôi có thể đưa ra, nhớ cho tôi về giải pháp Kirks cho bài kiểm tra Kobayashi Maru (bằng cách nào đó bị lừa): Ý tưởng là chúng tôi sử dụng ngăn xếp (và sử dụng nó để lập mô hình danh sách ). Tôi gọi các hoạt động en / dequeue và đẩy và bật, sau đó chúng tôi nhận được:

queue.new() : Stack1 = Stack.new(<Stack>);  
              Stack2 = Stack1;  

enqueue(element): Stack3 = Stack.new(<TypeOf(element)>); 
                  Stack3.push(element); 
                  Stack2.push(Stack3);
                  Stack3 = Stack.new(<Stack>);
                  Stack2.push(Stack3);
                  Stack2 = Stack3;                       

dequeue(): Stack3 = Stack1.pop(); 
           Stack1 = Stack1.pop();
           dequeue() = Stack1.pop()
           Stack1 = Stack3;

isEmtpy(): Stack1.isEmpty();

(StackX = StackY không sao chép nội dung, chỉ là bản sao của tham chiếu. Nó chỉ để mô tả dễ dàng. Bạn cũng có thể sử dụng một mảng gồm 3 ngăn xếp và truy cập chúng thông qua chỉ mục, ở đó bạn chỉ cần thay đổi giá trị của biến chỉ mục ). Mọi thứ đều ở O (1) theo thuật ngữ ngăn xếp hoạt động.

Và vâng tôi biết nó có thể tranh cãi, bởi vì chúng tôi đã ẩn chứa hơn 3 ngăn xếp, nhưng có lẽ nó mang lại cho bạn những ý tưởng hay khác.

EDIT: Ví dụ giải thích:

 | | | |3| | | |
 | | | |_| | | |
 | | |_____| | |
 | |         | |
 | |   |2|   | |
 | |   |_|   | |
 | |_________| |
 |             |
 |     |1|     |
 |     |_|     |
 |_____________|

Tôi đã thử ở đây với một chút nghệ thuật ASCII để hiển thị Stack1.

Mỗi phần tử được gói trong một ngăn xếp phần tử duy nhất (vì vậy chúng ta chỉ có ngăn xếp ngăn xếp kiểu an toàn).

Bạn thấy để loại bỏ chúng ta trước tiên bật phần tử đầu tiên (ngăn xếp chứa ở đây phần tử 1 và 2). Sau đó bật phần tử tiếp theo và mở khóa ở đó 1. Sau đó, chúng ta nói rằng ngăn xếp được bật đầu tiên bây giờ là Stack1 mới của chúng ta. Để nói rõ hơn một chút chức năng - đây là các danh sách được thực hiện bởi các ngăn xếp gồm 2 phần tử trong đó phần tử hàng đầu ist cdr và phần tử trên cùng đầu tiên / bên dưới là ô tô . Hai người còn lại đang giúp đỡ ngăn xếp.

Esp tricky là chèn, vì bạn bằng cách nào đó phải lặn sâu vào các ngăn xếp lồng nhau để thêm một yếu tố khác. Đó là lý do tại sao Stack2 ở đó. Stack2 luôn là ngăn xếp trong cùng. Thêm vào sau đó chỉ là đẩy một phần tử vào và sau đó đẩy một Stack2 mới (và đó là lý do tại sao chúng ta không được phép chạm vào Stack2 trong hoạt động dequeue của chúng ta).


Bạn có quan tâm để giải thích làm thế nào nó hoạt động? Có thể tìm ra cách đẩy 'A', 'B', 'C', 'D' và sau đó bật lên 4 lần?
MAK

1
@Iceman: Không có Stack2 là đúng. Chúng không bị mất, bởi vì Stack luôn đề cập đến ngăn xếp trong cùng trong Stack1, vì vậy chúng vẫn ẩn trong Stack1.
flolo

3
Tôi đồng ý rằng đó là gian lận :-). Đó không phải là 3 ngăn xếp, đó là 3 tham chiếu ngăn xếp. Nhưng một đọc thú vị.
Mark Peters

1
Đây là một sơ đồ thông minh, nhưng nếu tôi hiểu chính xác, cuối cùng nó sẽ cần n ngăn xếp khi có n phần tử được đẩy vào hàng đợi. Câu hỏi yêu cầu chính xác 3 ngăn xếp.
MAK

2
@MAK: Tôi biết, đó là lý do tại sao tuyên bố rõ ràng rằng nó bị lừa (tôi thậm chí đã dành danh tiếng cho tiền thưởng vì tôi cũng tò mò về giải pháp thực sự). Nhưng ít nhất bình luận của prusswan có thể được trả lời: Số lượng ngăn xếp là quan trọng, bởi vì giải pháp của tôi thực sự là hợp lệ, khi bạn có thể sử dụng nhiều như bạn muốn.
flolo

4

Tôi sẽ cố gắng làm một bằng chứng để chứng minh rằng nó không thể được thực hiện.


Giả sử có một hàng đợi Q được mô phỏng bởi 3 ngăn xếp A, B và C.

Khẳng định

  • ASRT0: = Hơn nữa, giả sử rằng Q có thể mô phỏng các hoạt động {queue, dequeue} trong O (1). Điều này có nghĩa là tồn tại một chuỗi cụ thể của việc đẩy / bật ngăn xếp cho mỗi hoạt động hàng đợi / dequeue được mô phỏng.

  • Không mất tính tổng quát, giả sử các hoạt động xếp hàng là xác định.

Đặt các phần tử được xếp hàng vào Q được đánh số 1, 2, ..., dựa trên thứ tự hàng đợi của chúng, với phần tử đầu tiên được xếp hàng vào Q được xác định là 1, phần thứ hai là 2, v.v.

Định nghĩa

  • Q(0) := Trạng thái của Q khi có 0 phần tử trong Q (và do đó 0 phần tử trong A, B và C)
  • Q(1) := Trạng thái của Q (và A, B và C) sau 1 thao tác xếp hàng trên Q(0)
  • Q(n) := Trạng thái của Q (và A, B và C) sau n hoạt động hàng đợi trên Q(0)

Định nghĩa

  • |Q(n)| :=số lượng phần tử trong Q(n)(do đó |Q(n)| = n)
  • A(n) := trạng thái của ngăn xếp A khi trạng thái của Q là Q(n)
  • |A(n)| := số lượng phần tử trong A(n)

Và định nghĩa tương tự cho ngăn xếp B và C.

Tầm thường

|Q(n)| = |A(n)| + |B(n)| + |C(n)|

---

|Q(n)| rõ ràng là không giới hạn trên n.

Do đó, ít nhất một trong số |A(n)|, |B(n)|hoặc |C(n)|không bị ràng buộc trên n.

WLOG1, giả sử ngăn xếp A không bị chặn và ngăn xếp B và C bị chặn.

Xác định * B_u :=giới hạn trên của B * C_u :=giới hạn trên của C *K := B_u + C_u + 1

WLOG2, với một n sao cho |A(n)| > K, chọn K phần tử từ Q(n). Giả sử rằng 1 trong số các phần tử đó nằm trong A(n + x)tất cả x >= 0, tức là phần tử luôn ở trong ngăn xếp A cho dù có bao nhiêu thao tác xếp hàng được thực hiện.

  • X := yếu tố đó

Sau đó chúng ta có thể định nghĩa

  • Abv(n) :=số lượng vật phẩm trong ngăn xếp A(n)cao hơn X
  • Blo(n) :=số phần tử trong ngăn xếp A(n)dưới X

    | A (n) | = Abv (n) + Blo (n)

ASRT1 :=Số lượng pops cần thiết để dequeue X từ Q(n)ít nhất làAbv(n)

Từ ( ASRT0) và ( ASRT1), ASRT2 := Abv(n)phải được giới hạn.

Nếu Abv(n)không bị ràng buộc, thì nếu 20 dequeues được yêu cầu để dequeue X từ Q(n)đó, nó sẽ yêu cầu ít nhất là Abv(n)/20pops. Đó là không giới hạn. 20 có thể là bất kỳ hằng số.

Vì thế,

ASRT3 := Blo(n) = |A(n)| - Abv(n)

phải không bị ràng buộc.


WLOG3, chúng ta có thể chọn các phần tử K từ dưới cùng A(n)và một trong số chúng nằm trong A(n + x)tất cảx >= 0

X(n) := phần tử đó, với bất kỳ n đã cho

ASRT4 := Abv(n) >= |A(n)| - K

Bất cứ khi nào một yếu tố được xếp hàng vào Q(n)...

WLOG4, giả sử B và C đã được điền vào giới hạn trên của chúng. Giả sử rằng giới hạn trên cho các yếu tố trên X(n)đã đạt được. Sau đó, một phần tử mới đi vào A.

WLOG5, giả sử rằng kết quả là, phần tử mới phải nhập bên dưới X(n).

ASRT5 := Số lượng pops cần thiết để đặt một phần tử bên dưới X(n) >= Abv(X(n))

Từ (ASRT4), Abv(n)không giới hạn trên n.

Do đó, số lượng pop cần thiết để đặt một phần tử bên dưới X(n)là không giới hạn.


Điều này mâu thuẫn ASRT1, do đó, không thể mô phỏng một O(1)hàng đợi với 3 ngăn xếp.


I E

Ít nhất 1 ngăn xếp phải được liên kết.

Đối với một phần tử nằm trong ngăn xếp đó, số lượng phần tử ở trên nó phải được giới hạn hoặc thao tác dequeue để loại bỏ phần tử đó sẽ không bị chặn.

Tuy nhiên, nếu số lượng phần tử ở trên nó bị giới hạn, thì nó sẽ đạt đến giới hạn. Tại một số điểm, một yếu tố mới phải nhập bên dưới nó.

Vì chúng ta luôn có thể chọn phần tử cũ trong số một trong số ít phần tử thấp nhất của ngăn xếp đó, nên có thể có một số phần tử không giới hạn ở trên nó (dựa trên kích thước không giới hạn của ngăn xếp không giới hạn).

Để nhập một phần tử mới bên dưới nó, vì có một số phần tử không bị chặn bên trên nó, nên một số lượng pop không giới hạn được yêu cầu để đặt phần tử mới bên dưới nó.

Và do đó mâu thuẫn.


Có 5 câu lệnh WLOG (Không mất tính tổng quát). Theo một cách hiểu nào đó, chúng có thể được hiểu theo trực giác là đúng (nhưng cho rằng chúng là 5, có thể mất một thời gian). Bằng chứng chính thức rằng không có tính tổng quát bị mất có thể được rút ra, nhưng cực kỳ dài. Họ đã bỏ qua.

Tôi thừa nhận rằng thiếu sót như vậy có thể để lại các câu lệnh WLOG trong câu hỏi. Với sự hoang tưởng của các lập trình viên về các lỗi, vui lòng xác minh các câu lệnh WLOG nếu bạn muốn.

Ngăn xếp thứ ba cũng không liên quan. Vấn đề là có một tập hợp các ngăn xếp giới hạn và một tập hợp các ngăn xếp không giới hạn. Tối thiểu cần thiết cho một ví dụ là 2 ngăn xếp. Số lượng ngăn xếp tất nhiên phải là hữu hạn.

Cuối cùng, nếu tôi đúng rằng không có bằng chứng, thì sẽ có một bằng chứng quy nạp dễ dàng hơn. Có lẽ dựa trên những gì xảy ra sau mỗi hàng đợi (theo dõi xem nó ảnh hưởng như thế nào đến trường hợp xấu nhất của dequeue với tập hợp tất cả các yếu tố trong hàng đợi).


2
Tôi nghĩ rằng bằng chứng hoạt động cho những giả định đó - nhưng tôi không chắc chắn rằng tất cả các ngăn xếp phải trống để hàng đợi trống hoặc tổng kích thước của các ngăn xếp phải bằng kích thước của hàng đợi.
Mikeb

3
"WLOG1, giả sử ngăn xếp A không bị ràng buộc và ngăn xếp B và C bị chặn." Bạn không thể cho rằng một số ngăn xếp bị chặn, vì điều đó sẽ khiến chúng trở nên vô dụng (chúng sẽ giống như lưu trữ bổ sung O (1)).
interjay

3
Đôi khi những điều tầm thường không phải là tầm thường: | Q | = | A | + | B | + | C | chỉ đúng, nếu bạn giả sử rằng với mỗi mục trong Q, bạn thêm chính xác một mục vào A, B hoặc C, nhưng có thể đó là thuật toán, luôn luôn thêm một phần tử hai lần vào hai ngăn xếp hoặc thậm chí cả ba. Và nếu nó hoạt động theo cách này, bạn WLOG1 không nắm giữ bất kỳ dài hơn (ví dụ như tưởng tượng C một bản sao của A (không phải là nó làm cho bất kỳ ý nghĩa, nhưng có lẽ đó là một thuật toán, với một trật tự khác nhau hoặc bất cứ điều gì ...)
flolo

@flolo và @mikeb: Cả hai bạn đều đúng. | Q (n) | nên được định nghĩa là | A (n) | + | B (n) | + | C (n) |. Và sau đó | Q (n) | > = n. Sau đó, bằng chứng sẽ hoạt động với n và lưu ý rằng miễn là | Q (n) | lớn hơn, kết luận áp dụng.
Đinh Phong Quek

@interjay: Bạn có thể có 3 ngăn xếp không giới hạn và không có ngăn xếp giới hạn. Sau đó, thay vì "B_u + C_u + 1", bằng chứng chỉ có thể sử dụng "1". Về cơ bản, biểu thức đại diện cho "tổng của giới hạn trên trong các ngăn xếp giới hạn + 1", do đó số lượng ngăn xếp giới hạn sẽ không thành vấn đề.
Đinh Phong Quek

3

Lưu ý: Điều này có nghĩa là một nhận xét cho việc thực hiện chức năng của hàng đợi thời gian thực (trường hợp xấu nhất liên tục) với các danh sách liên kết đơn. Tôi không thể thêm nhận xét do danh tiếng, nhưng sẽ rất tuyệt nếu ai đó có thể thay đổi nhận xét này thành nhận xét được thêm vào câu trả lời của antti.huima. Sau đó, một lần nữa, nó là hơi dài cho một nhận xét.

@ antti.huima: Danh sách liên kết không giống như một ngăn xếp.

  • s1 = (1 2 3 4) --- một danh sách được liên kết với 4 nút, mỗi nút chỉ vào một nút bên phải và giữ các giá trị 1, 2, 3 và 4

  • s2 = popped (s1) --- s2 hiện tại (2 3 4)

Tại thời điểm này, s2 tương đương với popped (s1), hoạt động giống như một ngăn xếp. Tuy nhiên, s1 vẫn có sẵn để tham khảo!

  • s3 = popped (popped (s1)) --- s3 là (3 4)

Chúng ta vẫn có thể nhìn trộm vào s1 để lấy 1, trong khi đó trong triển khai ngăn xếp thích hợp, phần tử 1 đã biến mất khỏi s1!

Điều đó có nghĩa là gì?

  • s1 là tham chiếu đến đỉnh của ngăn xếp
  • s2 là tham chiếu đến phần tử thứ hai của ngăn xếp
  • s3 là tham chiếu đến ...

Các danh sách liên kết bổ sung được tạo bây giờ mỗi cái phục vụ như một tham chiếu / con trỏ! Một số lượng hữu hạn các ngăn xếp không thể làm điều đó.

Từ những gì tôi thấy trong các bài báo / mã, các thuật toán đều sử dụng thuộc tính này của danh sách liên kết để giữ lại các tham chiếu.

Chỉnh sửa: Tôi chỉ đề cập đến 2 và 3 thuật toán danh sách liên kết sử dụng thuộc tính này của danh sách liên kết, khi tôi đọc chúng trước (chúng trông đơn giản hơn). Điều này không có nghĩa là cho thấy rằng chúng đang hoặc không thể áp dụng, chỉ để giải thích rằng các danh sách liên kết không nhất thiết phải giống hệt nhau. Tôi sẽ đọc một trong số 6 khi tôi rảnh. @Welbog: Cảm ơn đã sửa chữa.


Sự lười biếng cũng có thể mô phỏng chức năng con trỏ theo những cách tương tự.


Sử dụng danh sách liên kết giải quyết một vấn đề khác nhau. Chiến lược này có thể được sử dụng để thực hiện các hàng đợi thời gian thực trong Lisp (Hoặc ít nhất là Lisps khăng khăng xây dựng mọi thứ từ danh sách liên kết): Tham khảo "Hoạt động xếp hàng thời gian thực trong Pure Lisp" (được liên kết qua các liên kết của antti.huima). Đây cũng là một cách hay để thiết kế danh sách bất biến với thời gian hoạt động O (1) và các cấu trúc được chia sẻ (không thay đổi).


1
Tôi không thể nói với các thuật toán khác trong câu trả lời của antti, nhưng giải pháp thời gian không đổi sáu ngăn xếp ( eecs.usma.edu/webs/people/okasaki/jfp95/queue.hm.sml ) không sử dụng thuộc tính này của danh sách , như tôi đã triển khai lại nó trong Java bằng cách sử dụng java.util.Stackcác đối tượng. Nơi duy nhất sử dụng tính năng này là một tối ưu hóa cho phép các ngăn xếp bất biến được "nhân đôi" trong thời gian không đổi, điều mà các ngăn xếp Java cơ sở không thể thực hiện (nhưng có thể được thực hiện trong Java) vì chúng là các cấu trúc có thể thay đổi.
Welbog

Nếu đó là một tối ưu hóa không làm giảm độ phức tạp tính toán, thì nó sẽ không ảnh hưởng đến kết luận. Vui mừng cuối cùng cũng có một giải pháp, bây giờ để xác minh nó: Nhưng tôi không thích đọc SML. Tâm chia sẻ mã java của bạn? (:
Đinh Phong Quek

Thật không may, đây không phải là giải pháp cuối cùng vì nó sử dụng sáu ngăn xếp thay vì ba, thật không may. Tuy nhiên, có thể chứng minh rằng sáu ngăn xếp là một giải pháp tối thiểu ...
Welbog

@Welbog! Bạn có thể chia sẻ việc thực hiện 6 ngăn xếp của mình không? :) Thật tuyệt khi nhìn thấy nó :)
Antti Huima

1

Bạn có thể làm điều đó trong thời gian liên tục khấu hao với hai ngăn xếp:

------------- --------------
            | |
------------- --------------

Thêm O(1)và loại bỏ là O(1)nếu phía bạn muốn lấy không trống và O(n)nếu không (chia ngăn xếp khác thành hai).

Bí quyết là để thấy rằng O(n)hoạt động sẽ chỉ được thực hiện mỗi O(n)lần (nếu bạn tách, ví dụ như trong một nửa). Do đó, thời gian trung bình cho một hoạt động là O(1)+O(n)/O(n) = O(1).

Mặc dù điều này có thể xảy ra như một vấn đề, nhưng nếu bạn đang sử dụng một ngôn ngữ bắt buộc với ngăn xếp dựa trên mảng (nhanh nhất), thì bạn sẽ chỉ phải trả dần thời gian không đổi.


Đối với câu hỏi ban đầu: Việc tách một ngăn xếp thực sự đòi hỏi một ngăn xếp trung gian bổ sung. Đây có thể là lý do tại sao nhiệm vụ của bạn bao gồm ba ngăn xếp.
Thomas Ahle
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.