2012-05-14 42 views
14

Tôi vừa học về đệ quy bằng Python và đã hoàn thành nhiệm vụ, một trong số đó là đếm tất cả các phần tử trong danh sách các danh sách lồng nhau tùy ý. Tôi đã tìm kiếm trang web này và các câu trả lời được tìm thấy tất cả dường như sử dụng các cuộc gọi đệ quy. Vì nó đã được dạy rằng bất cứ điều gì có thể được biểu diễn đệ quy có thể được biểu diễn lặp đi lặp lại, và lặp lại được ưa thích trong Python, làm thế nào điều này sẽ được thực hiện mà không đệ quy hoặc mô-đun được nhập trong Python 2.6 (như một bài tập học tập)? (Một danh sách lồng nhau tự sẽ được tính là một yếu tố, như sẽ nội dung của nó.) Ví dụ:Đếm tất cả các phần tử trong danh sách danh sách lồng nhau tùy ý mà không đệ quy

>>> def element_count(p): 
...  count = 0 
...  for entry in p: 
...   count += 1 
...   if isinstance(entry, list):    
...    count += element_count(entry) 
...  return count 
>>> print element_count([1, [], 3]) 
3 
>>> print element_count([1, [1, 2, [3, 4]]]) 
7 
>>> print element_count([[[[[[[[1, 2, 3]]]]]]]]) 
10 

Làm thế nào điều này sẽ được viết bằng lặp?

+14

Lặp lại được ưu tiên cho những thứ như vòng lặp đơn giản. Đối với các vấn đề đệ quy vốn như thế này, đệ quy là tốt hơn. – interjay

+0

Đây là một bài tập học tập nhiều hơn là một tuyên bố về nguyên tắc. Và nó có vẻ dễ dàng hơn để thể hiện một giải pháp đệ quy. Tuy nhiên, nếu số lượng các cuộc gọi đệ quy cần thiết chưa được biết trước thì bài tập này có thực tế và cần thiết không? –

+1

Không nên 'element_count ([1, [1, 2, [3, 4]]])' là 5? Tại sao bạn tính các đối tượng danh sách con dưới dạng các phần tử? –

Trả lời

17

Dưới đây là một cách để làm điều đó:

def element_count(p): 
    q = p[:] 
    count = 0 
    while q: 
    entry = q.pop() 
    if isinstance(entry, list): 
     q += entry 
    count += 1 
    return count 

print element_count([1, [], 3]) 
print element_count([1, [1, 2, [3, 4]]]) 
print element_count([[[[[[[[1, 2, 3]]]]]]]]) 

Mã duy trì một danh sách các điều cần được xem xét. Bất cứ khi nào vòng lặp gặp một danh sách con, nó sẽ thêm nội dung của nó vào hàng đợi.

+4

Do giới hạn đệ quy được xây dựng trong của Python, nó thực sự * là * thường là một ý tưởng hay để triển khai các thuật toán đệ quy như các thuật toán lặp lại với một ngăn xếp rõ ràng. Tôi đang nghĩ về, ví dụ, DFS và các thuật toán đồ thị tương tự, sẽ vượt quá giới hạn đệ quy cho tất cả trừ những vấn đề nhỏ nhất. –

+3

Chức năng này có tính hủy diệt. Nó sẽ sửa đổi danh sách được truyền cho nó. –

+2

@NoufalIbrahim: Điểm công bằng. Đã cập nhật mã. – NPE

10

Thông thường mỗi vấn đề đệ quy có thể được chuyển đổi sang một lặp đi lặp lại bằng cách nào đó bằng cách sử dụng một chồng, trong trường hợp này một list:

def element_count(p): 
    elements = list(p) 
    count = 0 
    while elements: 
     entry = elements.pop() 
     count += 1 
     if isinstance(entry, list): 
      elements.extend(entry) 
    return count 
+0

về cơ bản giống với phiên bản @aix, nhưng giữ nguyên danh sách gốc – mata

+0

Tại sao trong khi được sử dụng thay vì trong ví dụ này? –

+1

'trong khi các phần tử' trong danh sách giống với' trong khi len (các phần tử)> 0', nó sẽ là đúng miễn là có một cái gì đó để 'pop' trong đó. khi chúng tôi tiếp tục thêm và xóa khỏi danh sách trong vòng lặp, vòng lặp 'for' sẽ không hoạt động ở đây. – mata

2

Bạn có thể tìm thấy phiên bản này của element_count được phần nào mạnh mẽ hơn những người khác. Nó có thể xử lý tất cả các thùng chứa hỗ trợ lặp lại, và nó xác định chính xác các thùng chứa đệ quy khi có một số lượng các phần tử vô hạn.

>>> def element_count(p): 
    stack, pointers, count = [iter(p)], set([id(p)]), 0 
    while stack: 
     for item in stack.pop(): 
      try: 
       iterator = iter(item) 
      except TypeError: 
       pass 
      else: 
       location = id(item) 
       if location in pointers: 
        return float('inf') 
       stack.append(iterator) 
       pointers.add(location) 
      count += 1 
    return count 

>>> element_count([1, [], 3]) 
3 
>>> element_count([1, [1, 2, [3, 4]]]) 
7 
>>> element_count([[[[[[[[1, 2, 3]]]]]]]]) 
10 
>>> p = [1, 2, 3] 
>>> element_count(p) 
3 
>>> p.append({4, 5, 6}) 
>>> element_count(p) 
7 
>>> p.append(p) 
>>> element_count(p) 
inf 
>>> 
+0

Điều này không làm tăng cú pháp SyntaxError: '{id (p)}'? –

+1

Xin lỗi về điều đó! Python 3.2.3 cho phép ký pháp đặt chữ.Ví dụ trên đã được sửa chữa để nó hoạt động cho bạn ngay bây giờ. –

+0

Điều này chắc chắn chiếm nhiều khả năng đầu vào hơn. Thú vị, cảm ơn! –

Các vấn đề liên quan