二维数组递归到二维双向链表
2D array to 2D doubly linked list by recursion
给定一个二维数组,仅使用递归创建一个二维双向链表。列表中的每个数字都必须有 4 个指针(上、下、右、左),并且需要链接到它旁边的每个数字(如果没有数字,则只是 'None')
import numpy as np
class Node:
""" Node class
up
|
left - data - right
|
down
"""
def __init__(self, data):
self.data = data
self.right = None
self.left = None
self.up = None
self.down = None
def constructDoublyLinkedListRecursion(arr):
""" Converts a 2D array into a 2D doubly linked list by calling
the recursee constructDLLRecursiveStep.
input:
arr: 2D array to turn into a 2D DLL
output:
head (top left node) of the 2D DLL of the input arr.
"""
return constructDLLRecursiveStep(arr, 0, 0, None)
def constructDLLRecursiveStep(arr, y, x, curr):
""" Recursively construct the 2D DLL from the given array.
This is the "recursee" of constructDoublyLinkedListRecursion.
input:
arr: The 2D array to construct the 2D DLL from.
y: y-coordinate of the array to get the value from.
x: x-coordinate of the array to get the value from.
curr: The current node to connect the new node from.
output:
new_node: The newly created node which connects to curr node.
"""
return new_node
这是我目前所做的:
def constructDLLRecursiveStep(arr, y, x, curr):
arrDim = arr.shape[1]
if(y >= arrDim or x >= arrDim):
return None;
new_node = Node(arr[y,x])
if(x > 0):
new_node.left = curr
else:
new_node.left = None
if(y > 0):
new_node.up = curr
else:
new_node.up = None
new_node.right = constructDLLRecursiveStep(arr, y, x+1, new_node)
new_node.down = constructDLLRecursiveStep(arr, y+1, x, new_node)
return new_node
显示功能
def display(dll_ptr):
""" Prints the 2D dll according to their positions similar to
printing a 2D array.
input:
dll_ptr: the head (most upper left node) of a 2D dll.
output:
None
"""
right_ptr = None
down_ptr = dll_ptr
while down_ptr != None:
right_ptr = down_ptr
while right_ptr != None:
msg = f"{right_ptr.data} | "
for i, direction in enumerate([("up", right_ptr.up), ("right", right_ptr.right), ("down", right_ptr.down), ("left", right_ptr.left)]):
direction_str, direction_ptr = direction
if direction_ptr: msg += f"{direction_str}: {direction_ptr.data}"
else: msg += f"{direction_str}: None"
msg += ", "
print(msg)
right_ptr = right_ptr.right
print()
down_ptr = down_ptr.down
我得到的输出表明向上指针存在问题:
"""
Input 2D array:
[[9 4 0 8 6]
[4 3 2 2 7]
[9 7 3 9 2]
[8 7 3 6 2]
[9 4 6 5 3]]
<class 'numpy.ndarray'>
constructDoublyLinkedListRecursion output:
9 4 0 8 6
4 3 2 2 7
9 7 3 9 2
8 7 3 6 2
9 4 6 5 3
constructDoublyLinkedListRecursion output:
9 | up: None, right: 4, down: 4, left: None,
4 | up: None, right: 0, down: 3, left: 9,
0 | up: None, right: 8, down: 2, left: 4,
8 | up: None, right: 6, down: 2, left: 0,
6 | up: None, right: None, down: 7, left: 8,
4 | up: 9, right: 3, down: 9, left: None,
3 | up: 4, right: 2, down: 7, left: 4,
2 | up: 3, right: 2, down: 3, left: 3,
2 | up: 2, right: 7, down: 9, left: 2,
7 | up: 2, right: None, down: 2, left: 2,
9 | up: 4, right: 7, down: 8, left: None,
7 | up: 9, right: 3, down: 7, left: 9,
3 | up: 7, right: 9, down: 3, left: 7,
9 | up: 3, right: 2, down: 6, left: 3,
2 | up: 9, right: None, down: 2, left: 9,
8 | up: 9, right: 7, down: 9, left: None,
7 | up: 8, right: 3, down: 4, left: 8,
3 | up: 7, right: 6, down: 6, left: 7,
6 | up: 3, right: 2, down: 5, left: 3,
2 | up: 6, right: None, down: 3, left: 6,
9 | up: 8, right: 4, down: None, left: None,
4 | up: 9, right: 6, down: None, left: 9,
6 | up: 4, right: 5, down: None, left: 4,
5 | up: 6, right: 3, down: None, left: 6,
3 | up: 5, right: None, down: None, left: 5,
"""
主要问题是你几乎无条件地在两个方向上重复出现。这意味着索引 1, 1 处的节点将通过两个不同的递归路径创建:一次是首先使用 x + 1 重复,然后使用 y + 1,第二次是在调用 y + 1 时递归使用 x + 1 进行调用。递归调用的总数远远超过您真正需要创建的节点数,因为正在创建通过矩阵的所有可能 (zig-zag) 路径。
一种解决方案是仅在 x 为零时使用 y + 1 进行递归调用。这将启动创建整行的过程(使用 x + 1 递归)。唯一需要注意的是将这些节点“nit”到它们上方的相应节点。但是你可以通过从左边的节点向上走然后走右边的节点来实现。
这是更正后的代码:
def constructDLLRecursiveStep(arr, y, x, curr):
leny, lenx = arr.shape
if y >= leny or x >= lenx:
return None
new_node = Node(arr[y,x])
if x == 0: # Came from above
new_node.up = curr
else: # Came from the left
new_node.left = curr
if y > 0: # Link to row above, by walking "the block"
curr.up.right.down = new_node
new_node.up = curr.up.right
new_node.right = constructDLLRecursiveStep(arr, y, x + 1, new_node)
if x == 0: # Recur downwards
new_node.down = constructDLLRecursiveStep(arr, y + 1, 0, new_node)
return new_node
给定一个二维数组,仅使用递归创建一个二维双向链表。列表中的每个数字都必须有 4 个指针(上、下、右、左),并且需要链接到它旁边的每个数字(如果没有数字,则只是 'None')
import numpy as np
class Node:
""" Node class
up
|
left - data - right
|
down
"""
def __init__(self, data):
self.data = data
self.right = None
self.left = None
self.up = None
self.down = None
def constructDoublyLinkedListRecursion(arr):
""" Converts a 2D array into a 2D doubly linked list by calling
the recursee constructDLLRecursiveStep.
input:
arr: 2D array to turn into a 2D DLL
output:
head (top left node) of the 2D DLL of the input arr.
"""
return constructDLLRecursiveStep(arr, 0, 0, None)
def constructDLLRecursiveStep(arr, y, x, curr):
""" Recursively construct the 2D DLL from the given array.
This is the "recursee" of constructDoublyLinkedListRecursion.
input:
arr: The 2D array to construct the 2D DLL from.
y: y-coordinate of the array to get the value from.
x: x-coordinate of the array to get the value from.
curr: The current node to connect the new node from.
output:
new_node: The newly created node which connects to curr node.
"""
return new_node
这是我目前所做的:
def constructDLLRecursiveStep(arr, y, x, curr):
arrDim = arr.shape[1]
if(y >= arrDim or x >= arrDim):
return None;
new_node = Node(arr[y,x])
if(x > 0):
new_node.left = curr
else:
new_node.left = None
if(y > 0):
new_node.up = curr
else:
new_node.up = None
new_node.right = constructDLLRecursiveStep(arr, y, x+1, new_node)
new_node.down = constructDLLRecursiveStep(arr, y+1, x, new_node)
return new_node
显示功能
def display(dll_ptr):
""" Prints the 2D dll according to their positions similar to
printing a 2D array.
input:
dll_ptr: the head (most upper left node) of a 2D dll.
output:
None
"""
right_ptr = None
down_ptr = dll_ptr
while down_ptr != None:
right_ptr = down_ptr
while right_ptr != None:
msg = f"{right_ptr.data} | "
for i, direction in enumerate([("up", right_ptr.up), ("right", right_ptr.right), ("down", right_ptr.down), ("left", right_ptr.left)]):
direction_str, direction_ptr = direction
if direction_ptr: msg += f"{direction_str}: {direction_ptr.data}"
else: msg += f"{direction_str}: None"
msg += ", "
print(msg)
right_ptr = right_ptr.right
print()
down_ptr = down_ptr.down
我得到的输出表明向上指针存在问题:
"""
Input 2D array:
[[9 4 0 8 6]
[4 3 2 2 7]
[9 7 3 9 2]
[8 7 3 6 2]
[9 4 6 5 3]]
<class 'numpy.ndarray'>
constructDoublyLinkedListRecursion output:
9 4 0 8 6
4 3 2 2 7
9 7 3 9 2
8 7 3 6 2
9 4 6 5 3
constructDoublyLinkedListRecursion output:
9 | up: None, right: 4, down: 4, left: None,
4 | up: None, right: 0, down: 3, left: 9,
0 | up: None, right: 8, down: 2, left: 4,
8 | up: None, right: 6, down: 2, left: 0,
6 | up: None, right: None, down: 7, left: 8,
4 | up: 9, right: 3, down: 9, left: None,
3 | up: 4, right: 2, down: 7, left: 4,
2 | up: 3, right: 2, down: 3, left: 3,
2 | up: 2, right: 7, down: 9, left: 2,
7 | up: 2, right: None, down: 2, left: 2,
9 | up: 4, right: 7, down: 8, left: None,
7 | up: 9, right: 3, down: 7, left: 9,
3 | up: 7, right: 9, down: 3, left: 7,
9 | up: 3, right: 2, down: 6, left: 3,
2 | up: 9, right: None, down: 2, left: 9,
8 | up: 9, right: 7, down: 9, left: None,
7 | up: 8, right: 3, down: 4, left: 8,
3 | up: 7, right: 6, down: 6, left: 7,
6 | up: 3, right: 2, down: 5, left: 3,
2 | up: 6, right: None, down: 3, left: 6,
9 | up: 8, right: 4, down: None, left: None,
4 | up: 9, right: 6, down: None, left: 9,
6 | up: 4, right: 5, down: None, left: 4,
5 | up: 6, right: 3, down: None, left: 6,
3 | up: 5, right: None, down: None, left: 5,
"""
主要问题是你几乎无条件地在两个方向上重复出现。这意味着索引 1, 1 处的节点将通过两个不同的递归路径创建:一次是首先使用 x + 1 重复,然后使用 y + 1,第二次是在调用 y + 1 时递归使用 x + 1 进行调用。递归调用的总数远远超过您真正需要创建的节点数,因为正在创建通过矩阵的所有可能 (zig-zag) 路径。
一种解决方案是仅在 x 为零时使用 y + 1 进行递归调用。这将启动创建整行的过程(使用 x + 1 递归)。唯一需要注意的是将这些节点“nit”到它们上方的相应节点。但是你可以通过从左边的节点向上走然后走右边的节点来实现。
这是更正后的代码:
def constructDLLRecursiveStep(arr, y, x, curr):
leny, lenx = arr.shape
if y >= leny or x >= lenx:
return None
new_node = Node(arr[y,x])
if x == 0: # Came from above
new_node.up = curr
else: # Came from the left
new_node.left = curr
if y > 0: # Link to row above, by walking "the block"
curr.up.right.down = new_node
new_node.up = curr.up.right
new_node.right = constructDLLRecursiveStep(arr, y, x + 1, new_node)
if x == 0: # Recur downwards
new_node.down = constructDLLRecursiveStep(arr, y + 1, 0, new_node)
return new_node