2009-06-17 7 views
41

tôi đang viết một hàm python mà nhìn một cái gì đó như thế nàyĐộ phức tạp thời gian chạy của các hàm danh sách python là gì?

def foo(some_list): 
    for i in range(0, len(some_list)): 
     bar(some_list[i], i) 

để nó được gọi với

x = [0, 1, 2, 3, ... ] 
foo(x) 

tôi đã giả định rằng truy cập chỉ mục của danh sách là O(1), nhưng rất ngạc nhiên khi thấy rằng cho các danh sách lớn, điều này chậm hơn đáng kể so với dự kiến ​​của tôi.

Câu hỏi của tôi, sau đó, là như thế nào là danh sách python được thực hiện, và mức độ phức tạp thời gian chạy các nội dung sau

  • Indexing là gì: list[x]
  • Popping từ cuối cùng: list.pop()
  • Popping từ bắt đầu: list.pop(0)
  • Mở rộng danh sách: list.append(x)

Để có thêm tín dụng, ghép nối hoặc tùy ý bật lên.

Trả lời

34

a very detailed table on python wiki mà trả lời câu hỏi của bạn.

Tuy nhiên, trong ví dụ cụ thể của bạn, bạn nên sử dụng enumerate để nhận chỉ mục của một vòng lặp có thể lặp lại trong vòng lặp. như vậy:

for i, item in enumerate(some_seq): 
    bar(item, i) 
+0

Tha thứ cho sự thiếu hiểu biết của tôi, nhưng đâu là sự phức tạp của 'pop()' trên trang đó? – Zaz

+2

@Zaz, pop() không có chỉ mục là O (1), với chỉ mục, ví dụ: đầu tiên trong danh sách, nó là O (n). vì bạn cần lấy mục O (1) và sau đó xóa nó. Sau đó có thời gian O (n) để sắp xếp tất cả các mục khác trong danh sách. Thêm thông tin về điều đó tại đây: https://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt –

7

Câu trả lời là "không xác định". Ngôn ngữ Python không xác định việc triển khai cơ bản. Dưới đây là một số liên kết đến một mailing list sợi bạn có thể quan tâm

Ngoài ra, cách Pythonic hơn viết vòng lặp của bạn sẽ được điều này.:

def foo(some_list): 
    for item in some_list: 
     bar(item) 
+0

Rất tiếc, tôi biết rằng phương pháp của tôi hơi kém so với Pythonic. Đối với vòng lặp của tôi, tôi cần mục, cũng như chỉ mục. Có cách nào tốt để làm điều đó không? (Chỉnh sửa câu hỏi của tôi) –

+6

use- for i, item in enumerate (some_lits): ... –

3

Không thể nhận xét, vì vậy

nếu bạn cần chỉ số và giá trị sau đó sử dụng enumerate:

for idx, item in enumerate(range(10, 100, 10)): 
    print idx, item 
6

Danh sách thực sự là O (1) để lập chỉ mục - chúng được thực hiện dưới dạng vectơ với phân bổ theo tỷ lệ, do đó, thực hiện nhiều như bạn mong đợi. Lý do có thể khiến bạn tìm mã này chậm hơn dự kiến ​​là cuộc gọi tới "range(0, len(some_list))".

range() tạo danh sách mới có kích thước được chỉ định, vì vậy nếu some_list có 1.000.000 mục, bạn sẽ tạo danh sách hàng triệu mục mới ở phía trước. Hành vi này thay đổi trong python3 (phạm vi là một iterator), mà tương đương python2 là xrange, hoặc thậm chí tốt hơn cho trường hợp của bạn, enumerate