簡體   English   中英

如何進行為單個列表構建的合並排序,而不是對“列表列表”進行排序?

[英]How do I make a merge sort, built for a single list, sort a "list of list" instead?

所以,假設我有一個這樣的列表:

[[0,9,8],[1, 7, 9],[2, 8, 9], [3, 5, 7]]

如果我想按每個子列表中的中間數字對其進行排序,結果會是這樣:

[[3, 5, 7],[2, 7, 9],[2, 8, 9],[0, 9, 8]]

我怎樣才能產生一個合並排序來對這樣的列表進行排序:

[1, 2, 3, 4]

要對列表列表進行排序並根據每個子列表的中間數指定要合並的列表? python有什么技巧可以讓它起作用嗎? 我唯一能找到的就是使用內置的排序功能,我不想這樣做。

下面是我正在實施的合並排序。 它是這樣工作的

歸並排序(list_here)

它合並了列表。 但是,我想使用一個技巧來根據列表列表進行 python 合並,而不是將每個子列表的中間索引作為正在比較的內容。

感謝您的任何指導。 下面是歸並排序:

def mergeSort(list_num):
    mergeSort2(list_num, 0, len(list_num)-1)


def mergeSort2(list_num, first, last):
    if first < last:
        middle = (first+last)//2
        mergeSort2(list_num, first, middle)
        mergeSort2(list_num, middle+1, last)
        merge(list_num, first, middle, last)


def merge(list_num, first, middle, last):
    L = list_num[first:middle+1]
    R = list_num[middle+1:last+1]
    L.append(sys.maxsize)
    R.append(sys.maxsize)
    i = j = 0

    for k in range(first, last+1):
        if L[i] <= R[j]:
            list_num[k] = L[i]
            i += 1
        else:
            list_num[k] = R[j]
            j += 1

這是一個可以接受鍵函數的代碼版本,就像內置的sort和相關函數一樣。

我使用max來創建“哨兵”值。 這是相當低效的,因為max必須掃描整個列表才能找到它的最大值。 此外,內置sort僅對其排序的列表中的每個項目調用一次 key 函數,而此代碼每次進行比較時都必須調用它兩次。

def mergeSort(list_num, key=None):
    mergeSort2(list_num, 0, len(list_num)-1, key=key)

def mergeSort2(list_num, first, last, key=None):
    if first < last:
        middle = (first+last)//2
        mergeSort2(list_num, first, middle, key=key)
        mergeSort2(list_num, middle+1, last, key=key)
        merge(list_num, first, middle, last, key=key)

def merge(list_num, first, middle, last, key=None):
    if key is None:
        key = lambda x: x

    L = list_num[first:middle+1]
    R = list_num[middle+1:last+1]
    sentinel = max(list_num, key=key)
    L.append(sentinel)
    R.append(sentinel)
    i = j = 0

    for k in range(first, last+1):
        if key(L[i]) <= key(R[j]):
            list_num[k] = L[i]
            i += 1
        else:
            list_num[k] = R[j]
            j += 1

# Test

lst = [3, 1, 4, 6, 5, 2]
print(lst)
mergeSort(lst)
print(lst)

lst = [[0, 9, 8], [1, 7, 9], [2, 8, 9], [3, 5, 7]]
print(lst)
mergeSort(lst, key=lambda x: x[1])
print(lst)

輸出

[3, 1, 4, 6, 5, 2]
[1, 2, 3, 4, 5, 6]
[[0, 9, 8], [1, 7, 9], [2, 8, 9], [3, 5, 7]]
[[3, 5, 7], [1, 7, 9], [2, 8, 9], [0, 9, 8]]

如您所見,它有效,但最好更改合並算法以消除哨兵,這樣我們就不需要max

我們還可以通過對數據執行Schwartzian 變換來提高效率,這樣每個 item 只需要調用一次 key 函數,但這確實會使代碼稍微復雜一些,當然它也需要更多的 RAM 來保存轉換后的數據。

如果沒有理解你的意思,下面的代碼就是你想要的:

l_sorted = sorted(l, key=lambda x: x[1])

其中 l 是您的輸入列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM