2020年10月27日 星期二

Algorithm_Sort_Quick sort

Algorithm_Sort_Quick sort

tags: Algorithms Sort python
import random
def quick_sort(input_array, is_random=False):
    """Quick Sort
    parameters:
        input_array: 輸入的未排序陣列
        is_random: 是否隨機取pivot point
             預設情況下是取陣列最後一個元素做pivot point      
    
    在worst case的情況下(資料已排序過),如果沒有亂數取pivot無法成功執行
    """
    # print(f'input array: {input_array}')
    array_size = len(input_array)
    if array_size < 2:
        # 不處理
        return input_array
    
    # 取得pivot
    if is_random:
        pivot_point = random.randint(0, array_size - 1)
    else:
        pivot_point = array_size - 1
    
    pivot = input_array.pop(pivot_point)
    # print(f'pivot: {pivot}, pivot_point: {pivot_point}')
        
    # 寫入比pivot大以及小的資料
    greater_pivot = [element for element in input_array if element > pivot]
    # print(f'greater_pivot: {greater_pivot}')
    lesser_pivot = [element for element in input_array if element < pivot]
    # print(f'lesser_pivot: {lesser_pivot}')
    # print(f'total: {lesser_pivot} + {[pivot]} + {greater_pivot}')
    # 利用python list相加的特性做遞迴處理
    return quick_sort(lesser_pivot, is_random) + [pivot] + quick_sort(greater_pivot, is_random)

下面給出五個資料集在不同資料量下的結果,其中

  • l1: 已經排序好的,由小到大
  • l2: 已經排序好的,但是逆排序,由大到小
  • l3: 亂數生成
  • l4: 亂數生成
  • l5: 亂數生成
Quick Sort(no random) 20000 40000 60000 80000 100000
l1
l2
l3 89 ms 172 ms 238 ms 438 ms 434 ms
l4 130 ms 153 ms 248 ms 330 ms 416 ms
l5 81 ms 154 ms 256 ms 335 ms 439 ms
Quick Sort(random) 20000 40000 60000 80000 100000
l1 154 ms 219 ms 315 ms 468 ms 583 ms
l2 107 ms 225 ms 333 ms 475 ms 539 ms
l3 103 ms 241 ms 370 ms 526 ms 592 ms
l4 121 ms 246 ms 349 ms 511 ms 656 ms
l5 111 ms 226 ms 403 ms 503 ms 627 ms

Algorithm_Sort_Heap srot

Algorithm_Sort_Heap srot

tags: Algorithms Sort python
def heapify(input_array, index, bound):
    """將資料結構化為heap
    parameters:
        input_array: 輸入的未排序陣列
        index: 要排序的root
        bound: 比較邊界,如果某個root的左、右索引已超過陣列長度就不處理
        
    假設,root的index=n,那其節點索引為
        root: n
        root_left_node: 2n + 1
        root_right_node: 2n + 2
        
    
    舉例來說,[0, 1, 2, 3, 4, 5, 6]
          0
        1   2
       3 4 5 6
    0為root,左邊節點為1,右邊則為2
    1為root,左邊節點為3,右邊則為4
    
    heap sort的一半是最後的節點,因此只會比較到陣列一半取上高斯
    其餘皆會是最終節點,不需要再比較,所以3456本身是不需要比較的
    我們會從2開始比,也就是7/2 = 3 - 1 = 2(因為python的索引初始值為0)
        
    要記得,python的索引是由0開始
    
    root永遠是三個節點中最大的(或最小的),但節點不考慮大小      
      5            5
    1   2        2   1 左邊兩種情況都可以
    """
    # 先預設最大值為root index
    largest_idx = index
    # print(f'init_array: {input_array}')
    # print(f'init_larget_idx: {largest_idx}, value: {input_array[largest_idx]}')
    left_idx = index * 2 + 1
    # print(f'left_idx: {left_idx}')
    right_idx = index * 2 + 2 
    # print(f'right_idx: {right_idx}')
    # 下面的比較,因為我們只關心root是最大的,因此不需要再比較左右兩邊
    # 注意到與陣列長度的比較條件必需在前面,不然會引發索引異常
    if  left_idx < bound  and input_array[largest_idx] < input_array[left_idx]:
        largest_idx = left_idx
        # print(f'l_larget_idx: {largest_idx}, value: {input_array[largest_idx]}')
    
    if right_idx < bound  and input_array[largest_idx] < input_array[right_idx]:        
        largest_idx = right_idx
        # print(f'r_larget_idx: {largest_idx}, value: {input_array[largest_idx]}')
    
    # 比較之後,如果最大值的異動,那就調整array的順序
    if largest_idx != index:        
        input_array[index], input_array[largest_idx] = input_array[largest_idx], input_array[index]
        # print(f'new array: {input_array}')
        # 遞迴處理heapify
        heapify(input_array, largest_idx, bound)
        
 def heap_sort(input_array):
    """heap sort"""
    array_size = len(input_array)
    # heap sort會從底層開始排序上來
    # 而且並不會所有的元素都排序,因為n//2 + 1之後的節點都是最終節點
    # 只有n//2 + 1之前是root,因此只做這邊的迴圈比較
    # 這邊只是做heap的結構
    for i in range(array_size // 2 - 1, -1, -1):        
        heapify(input_array, i, array_size)
    
    # 處理排序
    # 我們知道,經過heap過的結構,最大的一定是在最上面(假設是max heap)
    # 因此,實作上會將root的部份跟最後的結點做交換,再將n-1做一次heap
    for i in range(array_size - 1, 0, -1):
        # 每次heap之後都做頭尾的交換
        # print(f'heap_sort: {input_array}')
        input_array[0], input_array[i] = input_array[i], input_array[0]
        # 特別注意到,每一次迭代都會減少一個,因此這邊給的是迴圈中的i,而不是array_size
        heapify(input_array, 0, i)
    return input_array   

下面給出五個資料集在不同資料量下的結果,其中

  • l1: 已經排序好的,由小到大
  • l2: 已經排序好的,但是逆排序,由大到小
  • l3: 亂數生成
  • l4: 亂數生成
  • l5: 亂數生成
Heap Sort 20000 40000 60000 80000 100000
l1 416 ms 606 ms 864 ms 1.23 s 1.51 s
l2 255 ms 721 ms 876 ms 1.15 s 1.64 s
l3 265 ms 603 ms 923 ms 1.23 s 1.8 s
l4 297 ms 562 ms 946 m 1.16 s 1.59 s
l5 279 ms 553 ms 966 ms 1.22 s 1.66 s

2020年10月26日 星期一

Algorithm_Sort_Merge sort

Algorithm_Sort_Merge sort

tags: Algorithms Sort python
def merge(left_a, right_a):
    """合併兩個陣列"""
    def _merge():        
        while left_a and right_a:
#             print('_merge:', left_a, right_a)
            # 比較兩個陣列的第一個索引的值那一個比較小就優先回傳    
            yield (left_a if left_a[0] < right_a[0] else right_a).pop(0)
        yield from left_a
        yield from right_a
    return list(_merge())
        
def divide(input_array):
    """分割陣列"""
    # 取上高斯點做為中點切掉兩個陣列
    divide_point = len(input_array) // 2
    left_a = input_array[: divide_point]
    right_a = input_array[divide_point: ]
    return left_a, right_a  
    
def merge_sort(input_array):
    """利用遞迴呼執行分割、合併、排序"""
#     print('merge_sort_array:', input_array)
    if len(input_array) == 1:
#         print('return array:', input_array)
        return input_array
    left_a, right_a = divide(input_array)
    return merge(merge_sort(left_a), merge_sort(right_a))
    

下面給出五個資料集在不同資料量下的結果,其中

  • l1: 已經排序好的,由小到大
  • l2: 已經排序好的,但是逆排序,由大到小
  • l3: 亂數生成
  • l4: 亂數生成
  • l5: 亂數生成
Merge Sort 20000 40000 60000 80000 100000
l1 261 ms 585 ms 805 ms 1.35 s 2.18 s
l2 199 ms 528 ms 880 ms 1.47 s 2.09 s
l3 294 ms 844 ms 1.52 s 2.37 s 3.64 s
l4 282 ms 761 ms 1.45 s 2.39 s 3.42 s
l5 331 ms 735 ms 1.5 s 2.27 s 3.48 s

Algorithm_Sort_Insrtion sort

Algorithm_Sort_Insrtion sort

tags: Algorithms Sort python
def insertion_sort(input_array):
    """insertion sort
    input_array: list
                 list內的元素需為數值
                 
    return 
        由小大到排序後的list
    """
    if len(input_array) <= 1:
        return
    
    # 從第2個element開始處理
    for idx, idx_value in enumerate(input_array[1: ]):        
        # 內圈迴圈使用        
        inner_idx = idx        
        while inner_idx >= 0 and idx_value < input_array[inner_idx]:            
            # 這邊的idx剛好就是j-1的索引
            # 判斷兩值的大小,如果索引值(右)比前一個元素(左)小
            # 那就將前一個元素複製到索引處                                       
            input_array[inner_idx + 1] = input_array[inner_idx]                
            inner_idx -= 1            
        
        # 當兩個索引不同代表異動排序過
        if inner_idx != idx:                
            # 將原始索引值寫入最終停止的索引處            
            input_array[inner_idx + 1] = idx_value
    
    return input_array

下面給出五個資料集在不同資料量下的結果,其中

  • l1: 已經排序好的,由小到大
  • l2: 已經排序好的,但是逆排序,由大到小
  • l3: 亂數生成
  • l4: 亂數生成
  • l5: 亂數生成
Insertion sort 20000 40000 60000 80000 100000
l1 7ms 16ms 25ms 22ms 37ms
l2 1min 31s 5min 47s 13min 27s 24min 18s 37min 34s
l3 43.4s 2min 59s 6min 52s 12min 27s 20min 6s
l4 43.1s 3min 2s 6min 50s 13min 1s 19min 52s
l5 42.9s 2min 57s 6min 51s 12min 42s 19min 47s

2020年10月21日 星期三

SAP_ABAP_邊學邊記錄_取得internal table的資料筆數

在ABAP中,如果想要從interlnal table取得目前表內的資料筆數,只需要透過下面的語法就可以完成
DESCRIBE TABLE your_internal_table LINES your_variable.