Trong C#, chiến lược được sử dụng để phát triển bộ đệm trong được sử dụng bởi một StringBuilder đã thay đổi theo thời gian.
Có ba chiến lược cơ bản để giải quyết vấn đề này và chúng có đặc điểm hiệu suất khác nhau.
Chiến lược cơ bản đầu tiên là:
- Hãy một mảng kí tự
- Khi bạn chạy ra khỏi phòng, tạo ra một mảng mới với k nhiều ký tự, đối với một số k không đổi.
- Sao chép mảng cũ vào mảng mới, và mồ côi mảng cũ.
Chiến lược này có một số vấn đề, rõ ràng nhất trong số đó là O (n) trong thời gian nếu chuỗi được tạo là vô cùng lớn. Giả sử k là một nghìn ký tự và chuỗi cuối cùng là một triệu ký tự. Bạn kết thúc việc phân bổ lại chuỗi tại 1000, 2000, 3000, 4000, ... và do đó sao chép 1000 + 2000 + 3000 + 4000 + ... + 999000 ký tự, được tính vào thứ tự 500 tỷ ký tự được sao chép!
Chiến lược này có thuộc tính tốt đẹp là lượng bộ nhớ "bị lãng phí" bị giới hạn bởi k.
Trong thực tế, chiến lược này hiếm khi được sử dụng vì vấn đề n bình phương đó.
Chiến lược cơ bản thứ hai là
- Hãy một mảng
- Khi bạn chạy ra khỏi phòng, tạo ra một mảng mới với k% nhân vật hơn, đối với một số k không đổi.
- Sao chép mảng cũ vào mảng mới, và mồ côi mảng cũ.
k% thường là 100%; nếu nó là sau đó điều này được gọi là chiến lược "tăng gấp đôi khi đầy đủ".
Chiến lược này có thuộc tính tốt đẹp là khấu hao chi phí là O (n). Giả sử một lần nữa chuỗi cuối cùng là một triệu ký tự và bạn bắt đầu với một nghìn. Bạn tạo bản sao ở 1000, 2000, 4000, 8000, ... và kết thúc sao chép 1000 + 2000 + 4000 + 8000 ... + 512.000 ký tự, tổng cộng khoảng một triệu ký tự được sao chép; tốt hơn nhiều.
Chiến lược có thuộc tính rằng chi phí phân bổ là tuyến tính bất kể tỷ lệ phần trăm bạn chọn.
Chiến lược này có một số nhược điểm mà đôi khi một hoạt động sao chép là cực kỳ đắt, và bạn có thể lãng phí lên đến k% chiều dài chuỗi thức trong bộ nhớ không sử dụng.
Chiến lược thứ ba là tạo một danh sách liên kết các mảng, mỗi mảng có kích thước k. Khi bạn tràn một mảng hiện có, một mảng mới sẽ được cấp phát và nối vào cuối danh sách.
Chiến lược này có thuộc tính tốt đẹp mà không hoạt động đặc biệt tốn kém, tổng số bộ nhớ bị lãng phí bị giới hạn bởi k, và bạn không cần phải xác định khối lượng lớn trong heap một cách thường xuyên. Nó có nhược điểm mà cuối cùng biến điều thành một chuỗi có thể tốn kém như các mảng trong danh sách liên kết có thể có địa phương nghèo.
Trình tạo chuỗi trong khuôn khổ .NET được sử dụng để sử dụng chiến lược gấp đôi khi toàn bộ; nó bây giờ sử dụng một chiến lược liên kết danh sách các khối.
IIRC, .NET StringBuilder sẽ ít nhất tăng gấp đôi kích thước bộ đệm hiện tại nếu bạn cố gắng nối thêm thứ gì đó sẽ yêu cầu tăng kích thước. –
Số tiền báo cáo là 1.6180339887 ...: tỷ lệ vàng, * nhưng chỉ sử dụng 2 * – pmg
@ChrisFarmer: Đó là chiến lược trong quá khứ; phiên bản hiện tại sử dụng một chiến lược khác. –