我有一个圆增长算法(带闭合链接的线增长),每次迭代时都会在现有点之间添加新点。
每个点的链接信息作为元组存储在列表中。该列表是迭代更新的。
问题:
将这些点的空间顺序作为列表返回的最有效方法是什么?
我是否需要在每次迭代中计算整个顺序,或者是否有办法将新点有序地累积插入该列表中?
我所能想到的是以下内容:
tuples = [(1, 4), (2, 5), (3, 6), (1, 6), (0, 7), (3, 7), (0, 8), (2, 8), (5, 9), (4, 9)]
starting_tuple = [e for e in tuples if e[0] == 0 or e[1] == 0][0]
## note: 'starting_tuple' could be either (0, 7) or (0, 8), starting direction doesn't matter
order = list(starting_tuple) if starting_tuple[0] == 0 else [starting_tuple[1], starting_tuple[0]]
## order will always start from point 0
idx = tuples.index(starting_tuple)
## index of the starting tuple
def findNext():
global idx
for i, e in enumerate(tuples):
if order[-1] in e and i != idx:
ind = e.index(order[-1])
c = 0 if ind == 1 else 1
order.append(e[c])
idx = tuples.index(e)
for i in range(len(tuples)/2):
findNext()
print order
它正在工作,但是既不优雅(非pythonic),也不高效。 在我看来,递归算法可能更合适,但不幸的是我不知道如何实现这种解决方案。
另外,请注意,我正在使用Python 2,并且只能访问完整的python软件包(无numpy)
答案 0 :(得分:2)
由于节点仅链接到其他两个节点,因此您可以按数字对它们进行分箱,然后跟随数字。这是O(n)排序,这很可靠,但是从<,>,=的意义上来说不是真正的排序。
def bin_nodes(node_list):
#figure out the in and out nodes for each node, and put those into a dictionary.
node_bins = {} #init the bins
for node_pair in node_list: #go once through the list
for i in range(len(node_pair)): #put each node into the other's bin
if node_pair[i] not in node_bins: #initialize the bin dictionary for unseen nodes
node_bins[node_pair[i]] = []
node_bins[node_pair[i]].append(node_pair[(i+1)%2])
return node_bins
def sort_bins(node_bins):
#go from bin to bin, following the numbers
nodes = [0]*len(node_bins) #allocate a list
nodes[0] = next(iter(node_bins)) #pick an arbitrary one to start
nodes[1] = node_bins[nodes[0]][0] #pick a direction to go
for i in range(2, len(node_bins)):
#one of the two nodes in the bin is the horse we rode in on.
#The other is the next stop.
j = 1 if node_bins[nodes[i-1]][0] == nodes[i-2] else 0 #figure out which one ISN"T the one we came in on
nodes[i] = node_bins[nodes[i-1]][j] #pick the next node, then go to its bin, rinse repeat
return nodes
if __name__ == "__main__":
#test
test = [(1,2),(3,4),(2,4),(1,3)] #should give 1,3,4,2 or some rotation or reversal thereof
print(bin_nodes(test))
print(sort_bins(bin_nodes(test)))
答案 1 :(得分:2)
对我而言,这似乎更像是字典和生成器问题,而不是递归:
from collections import defaultdict
def findNext(tuples):
previous = 0
yield previous # our first result
dictionary = defaultdict(list)
# [(1, 4), (2, 5), (3, 6), ...] -> {0: [7, 8], 1: [4, 6], 2: [5, 8], ...}
for a, b in tuples:
dictionary[a].append(b)
dictionary[b].append(a)
current = dictionary[0][0] # dictionary[0][1] should also work
yield current # our second result
while True:
a, b = dictionary[current] # possible connections
following = a if a != previous else b # only one will move us forward
if following == 0: # have we come full circle?
break
yield following # our next result
previous, current = current, following # reset for next iteration
tuples = [(1, 4), (2, 5), (3, 6), (1, 6), (7, 0), (3, 7), (8, 0), (2, 8), (5, 9), (4, 9)]
generator = findNext(tuples)
for n in generator:
print n
输出
% python test.py
0
7
3
6
1
4
9
5
2
8
%
算法当前假设我们有两个以上的节点。