排序方法&最小生成树

冒泡排序

简单地说就是两层循环,第一次循环每循环一次就找到一个最大的排到列表的尾部(通过第二层循环里面不停的交换),这样第一次循环循环数组的长度次数,就可得到一个排序好的数组。

def bubbleSort(input_list):
    n=len(input_list)
    if n==0:
        return []
    sorted_list=input_list
    for i in  range(n-1):
        bChanged=False
        print('第%d趟排序:'%(i+1))
        for j in range (n-1):
            if sorted_list[j+1]<sorted_list[j]:
                sorted_list[j],sorted_list[j+1]=sorted_list[j+1],sorted_list[j]
            print(sorted_list)
    return sorted_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=bubbleSort(input_list)
print('排序后',sorted_list)

def bubbleSort(input_list):
    n=len(input_list)
    for i in range(n-1):
        bchanged=False
        for j in range(n-1):
            if input_list[j]>input_list[j+1]:
                input_list[j],input_list[j+1]=input_list[j+1],input_list[j]
                bchanged=True
        if bchanged==False:
            return input_list
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=bubbleSort(input_list)
print('排序后',sorted_list)
# print(bubbleSort([]))
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
[]

直接插入排序

直接插入排序就是先从头到后面遍历一遍,然后对于每一个都遍历这个元素之前的元素使其插入到合适的位置,由于是从头往前遍历所以该元素之前的元素本身已经是排序好的元素了,我们需要做的事情只是将该元素插入合适的位置。

def insertSort(input_list):
    n=len(input_list)
    for i in range(n):
        for j in range(i)[::-1]:
            if input_list[j+1]<input_list[j]:
                input_list[j+1],input_list[j]=input_list[j],input_list[j+1]
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=insertSort(input_list)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
def insertSort(input_list):
    n=len(input_list)
    for i in range(n):
        j=i-1
        temp=input_list[i]
        while j>=0 and temp<input_list[j]:
            input_list[j+1]=input_list[j]
            j-=1
        input_list[j+1]=temp
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=insertSort(input_list)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

希尔排序

希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。
希尔排序,也称递减增量排序算法,以其设计者希尔(Donald Shell)的名字命名,该算法由 1959 年公布。

希尔排序,他的主要思想是先把比较大放到后面,然后把比较小的移到前面去。你想他开始以gap这个步长。然后集体就可以并行的集体的去往后移这个操作。这样的话,它就是可以用多处理器来进行处理,而不是用单个处理器一个一个的来进行处理。

def shellSort(input_list):
    n=len(input_list)
    if n<=1:
        return input_list
    gap=n//2
    while gap>0:
        for i in range(gap,n):
            j=i-gap
            temp=input_list[i]
            while j>=0 and input_list[j]>temp:
                input_list[j+gap]=input_list[j]
                j-=gap
            input_list[j+gap]=temp
        gap//=2
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=shellSort(input_list)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

快速排序

快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分:分割点左边都是比它小的数,右边都是比它大的数。
然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

def QuickSort(input_list,left,right):
    def mid(input_list,left,right):
        mid=input_list[left]
        while left<right:
            while left<right and input_list[right]>mid:
                right-=1
            input_list[left]=input_list[right]
            while left<right and input_list[left]<mid:
                left+=1
            input_list[right]=input_list[left]
            input_list[left]=mid
        return left
    if left<right:
        mid=mid(input_list,left,right)
        QuickSort(input_list,left,mid-1)
        QuickSort(input_list,mid+1,right)
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=QuickSort(input_list,0,len(input_list)-1)
print('排序后',sorted_list)
        
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
def QuickSort(input_list,left,right):
    i=left
    j=right
    mid=input_list[i]
    while i<j:
        while i<j and input_list[j]>mid:
            j-=1
        while i<j and input_list[i]<mid:
            i+=1
        if i<j:
            input_list[i],input_list[j]=input_list[j],input_list[i]
            i+=1
            j-=1
    if left<right:
        QuickSort(input_list,left,i-1)
        QuickSort(input_list,j+1,right)
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=QuickSort(input_list,0,len(input_list)-1)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

简单选择排序

遍历一遍数组,每趟排序中,将当前第 i 小的元素放在位置 i 上。

def SelectSort(input_list):
    n=len(input_list)
    for i in range(n):
        temp=input_list[i]
        min_index=i
        for j in range(i,n):
            if input_list[j]<temp:
                temp=input_list[j]
                min_index=j
        imput_list[i],input_list[min_index]=input_list[min_index],input_list[i]
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=QuickSort(input_list,0,len(input_list)-1)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

堆排序

  1. 根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。
  2. 每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大根堆。
def HeadSort(input_list):
    n=len(input_list)
    def HeadAdjust(input_list,parent,length):
        child=2*parent+1
        temp=input_list[parent]
        while child<length:
            if child+1<length and input_list[child]<input_list[child+1]:
                child+=1
            if temp>input_list[child]:
                break
            input_list[parent]=input_list[child]
            parent=child
            child=2*parent+1
        input_list[parent]=temp
    for i in range(n//2)[::-1]:
        HeadAdjust(input_list,i,n)
    for j in range(n)[::-1]:
        input_list[j],input_list[0]=input_list[0],input_list[j]
        HeadAdjust(input_list,0,j)
    return input_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=HeadSort(input_list)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

def MergeSort(input_list):
    def merge(left,right):
        temp=[]
        i=0
        j=0
        while i<len(left) and j<len(right):
            if left[i]<right[j]:
                temp.append(left[i])
                i+=1
            else:
                temp.append(right[j])
                j+=1
        while i<len(left):
            temp.append(left[i])
            i+=1
        while j<len(right):
            temp.append(right[j])
            j+=1
        return temp
    def merge_sort(input_list):
        if len(input_list)<=1:
            return input_list
        mid=len(input_list)//2
        left=merge_sort(input_list[:mid])
        right=merge_sort(input_list[mid:])
        return merge(left,right)
    sort_list=merge_sort(input_list)
    return sort_list
input_list=[50,123,543,187,49,30,0,2,11,100]
print('排序前',input_list)
sorted_list=MergeSort(input_list)
print('排序后',sorted_list)
排序前 [50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
排序后 [0, 2, 11, 30, 49, 50, 100, 123, 187, 543]

最小生成树

kruskal算法基本思路:先对边按权重从小到大排序,先选取权重最小的一条边,如果该边的两个节点均为不同的分量,则加入到最小生成树,否则计算下一条边,直到遍历完所有的边。

prim算法基本思路:所有节点分成两个group,一个为已经选取的selected_node(为list类型),一个为candidate_node,首先任取一个节点加入到selected_node,然后遍历头节点在selected_node,尾节点在candidate_node的边,选取符合这个条件的边里面权重最小的边,加入到最小生成树,选出的边的尾节点加入到selected_node,并从candidate_node删除。直到candidate_node中没有备选节点(这个循环条件要求所有节点都有边连接,即边数要大于等于节点数-1,循环开始前要加入这个条件判断,否则可能会有节点一直在candidate中,导致死循环)。


class Graph(object):
    def __init__(self, maps):
        self.maps = maps
        self.nodenum = self.get_nodenum()
        self.edgenum = self.get_edgenum()
 
    def get_nodenum(self):
        return len(self.maps)
 
    def get_edgenum(self):
        count = 0
        for i in range(self.nodenum):
            for j in range(i):
                if self.maps[i][j] > 0 and self.maps[i][j] < 9999:
                    count += 1
        return count
 
    def kruskal(self):
        res = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
            return res
        edge_list = []
        for i in range(self.nodenum):
            for j in range(i,self.nodenum):
                if self.maps[i][j] < 9999:
                    edge_list.append([i, j, self.maps[i][j]])#按[begin, end, weight]形式加入
        edge_list.sort(key=lambda a:a[2])#已经排好序的边集合
        
        group = [[i] for i in range(self.nodenum)]
        for edge in edge_list:
            for i in range(len(group)):
                if edge[0] in group[i]:
                    m = i
                if edge[1] in group[i]:
                    n = i
            if m != n:
                res.append(edge)
                group[m] = group[m] + group[n]
                group[n] = []
        return res
 
    def prim(self):
        res = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
            return res
        res = []
        seleted_node = [0]
        candidate_node = [i for i in range(1, self.nodenum)]
        
        while len(candidate_node) > 0:
            begin, end, minweight = 0, 0, 9999
            for i in seleted_node:
                for j in candidate_node:
                    if self.maps[i][j] < minweight:
                        minweight = self.maps[i][j]
                        begin = i
                        end = j
            res.append([begin, end, minweight])
            seleted_node.append(end)
            candidate_node.remove(end)
        return res
 
max_value = 9999
row0 = [0,7,max_value,max_value,max_value,5]
row1 = [7,0,9,max_value,3,max_value]
row2 = [max_value,9,0,6,max_value,max_value]
row3 = [max_value,max_value,6,0,8,10]
row4 = [max_value,3,max_value,8,0,4]
row5 = [5,max_value,max_value,10,4,0]
maps = [row0, row1, row2,row3, row4, row5]
graph = Graph(maps)
print('邻接矩阵为\n%s'%graph.maps)
print('节点数据为%d,边数为%d\n'%(graph.nodenum, graph.edgenum))
print('------最小生成树kruskal算法------')
print(graph.kruskal())
print('------最小生成树prim算法')
print(graph.prim())

邻接矩阵为
[[0, 7, 9999, 9999, 9999, 5], [7, 0, 9, 9999, 3, 9999], [9999, 9, 0, 6, 9999, 9999], [9999, 9999, 6, 0, 8, 10], [9999, 3, 9999, 8, 0, 4], [5, 9999, 9999, 10, 4, 0]]
节点数据为6,边数为8

------最小生成树kruskal算法------
[[1, 4, 3], [4, 5, 4], [0, 5, 5], [2, 3, 6], [3, 4, 8]]
------最小生成树prim算法
[[0, 5, 5], [5, 4, 4], [4, 1, 3], [4, 3, 8], [3, 2, 6]]

猜你喜欢

转载自blog.csdn.net/weixin_45569785/article/details/107872671