Oracle plsql排序算法

create or replace package plsql_algorithm is

  -- Author  : cs
  -- Created : 2019/9/4 14:27:08
  -- Purpose : plsql排序算法

  N constant int := 9;

  -- 數組類型
  type typ_array is table of int index by pls_integer;

  --初始化數組
  procedure init_array;
  procedure init_array_asc;
  procedure init_array_desc;

  --打印數組
  procedure print_array;
  --*********************常用排序算法*********************
  -- 選擇排序
  procedure selectionSort;

  -- 冒泡排序
  procedure bubbleSort;

  -- 插入排序
  procedure insertSort;

  -- 快速排序
  procedure quickSort(p int default 1, r int default N);
  function Partition(p int, r int) return int;

  --歸併排序
  procedure mergeSort(p int default 1, r int default N);
  procedure merge(p int, r int);
end plsql_algorithm;
create or replace package body plsql_algorithm is

  -- 私有靜態變量-數組長度
  --n constant int := 9;

  -- 私有變量
  array typ_array;

  -- 臨時數組--歸併排序用
  array_tmp typ_array;

  --初始化數組
  procedure init_array is
  begin
    -- 初始化
    array(1) := 8;
    array(2) := 1;
    array(3) := 2;
    array(4) := 7;
    array(5) := 4;
    array(6) := 6;
    array(7) := 3;
    array(8) := 9;
    array(9) := 5;
  end init_array;

  procedure init_array_asc is
  begin
    -- 初始化
    array(1) := 1;
    array(2) := 2;
    array(3) := 3;
    array(4) := 4;
    array(5) := 5;
    array(6) := 6;
    array(7) := 7;
    array(8) := 8;
    array(9) := 9;
  end init_array_asc;

  procedure init_array_desc is
  begin
    -- 初始化
    array(1) := 9;
    array(2) := 8;
    array(3) := 7;
    array(4) := 6;
    array(5) := 5;
    array(6) := 4;
    array(7) := 3;
    array(8) := 2;
    array(9) := 1;
  end init_array_desc;

  --打印數組
  procedure print_array is
  begin
    for i in 1 .. n - 1 loop
      dbms_output.put(array(i) || '->');
    end loop;
    dbms_output.put(array(n));
    dbms_output.put_line('');
  end print_array;

  -- selectionsort
  /*
  選擇排序(以升序排序爲例):
  每次從未排序區間選擇一個最小的元素,放在已排序的末尾
  */
  procedure selectionSort is
    i int;
    j int;
    m int; --最小值下標
    t int; --交換使用的臨時變量
  begin
  
    --排序代碼
    for i in 1 .. n loop
      --尋找最小元素
      m := i;
      for j in i + 1 .. n loop
        if (array(j) < array(m)) then
          m := j;
        end if;
      end loop;
      --交換
      t := array(i);
      array(i) := array(m);
      array(m) := t;
    end loop;
  
  end selectionSort;

  -- bubblesort
  /*
    冒泡排序(以升序排序爲例):
  它重複地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果他們的順序(如從大到小、首字母從a到z)錯誤就把他們交換過來。
  走訪元素的工作是重複地進行直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。
    */
  procedure bubbleSort is
    i    int;
    j    int;
    t    int; --交換使用的臨時變量
    flag int := 0; --交換標記,如果一次冒泡沒有元素交換,說明已經有序了,不需要再冒泡了
  begin
  
    --排序代碼
    for i in 1 .. n loop
      flag := 0; --交換標記
    
      for j in 1 .. n - i loop
        --如果前者大於後者,交換
        if (array(j) > array(j + 1)) then
          flag := 1;
          t := array(j);
          array(j) := array(j + 1);
          array(j + 1) := t;
        end if;
      end loop;
    
      --已經有序了,不需要再冒泡了,跳出
      if (flag = 0) then
        goto next_loop;
      end if;
    
    end loop;
  
    <<next_loop>>
    null; --不可少 
  
  end bubbleSort;

  -- insertSort
  /*
  插入排序(以升序排序爲例):
  每次從未排序區間選擇第一個元素,插入到已排序區間。
  */
  procedure insertSort is
    i int;
    j int;
    t int; --交換使用的臨時變量
  begin
  
    --排序代碼
    for i in 1 .. n loop
      for j in reverse 2 .. i loop
        --查找插入位置
        if (array(j) < array(j - 1)) then
          t := array(j - 1);
          array(j - 1) := array(j);
          array(j) := t;
        end if;
      end loop;
    
    end loop;
  
  end insertSort;

  -- quickSort
  /*
    快速排序(以升序排序爲例):
  遞歸實現
  每次從區間末尾選取一個元素,將區間分爲2部分,前半部分小於給定值,後半部分大於等於給定值  
  需要先實現一個partition分區函數
  */
  procedure quickSort(p int, r int) is
  
    q int;
  
  begin
    --遞歸結束條件
    if (p >= r) then
      return;
    end if;
  
    --排序代碼
    q := Partition(p, r);
    quickSort(p, q - 1);
    quickSort(q + 1, r);
  
  end quickSort;

  function Partition(p int, r int) return int is
    i     int;
    j     int;
    t     int;
    pivot int; --分隔元素的值,默認選區間最後一個
    q     int; --排序完成後,分割點的下標
  begin
    i     := p;
    j     := p;
    pivot := array(r);
    --i指正依次後退,j指針在發生元素交換時後退(元素小於pivot時),指向下一個交換位置
    for i in p .. r - 1 loop
      if (array(i) < pivot) then
        --交換i和j的元素,同時j後移
        t := array(i);
        array(i) := array(j);
        array(j) := t;
        j := j + 1;
      end if;
    end loop;
    --交換array(j)和pivot
    t := array(j);
    array(j) := pivot;
    array(r) := t;
    q := j;
    --dbms_output.put_line(q);
    return q;
  end Partition;

  --歸併排序
  procedure mergeSort(p int, r int) is
    q int;
  begin
    q := trunc((p + r) / 2); --中點,前半部分的最後一個元素下標
    if (r <= p) then
      return;
    end if;
  
    mergeSort(p, q);
    mergeSort(q + 1, r);
    merge(p, r);
  end mergeSort;

  procedure merge(p int, r int) is
    q int;
    i int;
    j int;
    k int := p; --臨時數組指針
  begin
    q := trunc((p + r) / 2); --中點,前半部分的最後一個元素下標
    i := p; --前半部分指針
    j := q + 1; --後半部分指針
    while (i <= q and j <= r) loop
      if (array(j) < array(i)) then
        array_tmp(k) := array(j);
        j := j + 1;
        k := k + 1;
      else
        array_tmp(k) := array(i);
        i := i + 1;
        k := k + 1;
      end if;
    end loop;
  
    --剩下的直接拷貝
    while (i <= q) loop
      array_tmp(k) := array(i);
      i := i + 1;
      k := k + 1;
    end loop;
  
    while (j <= r) loop
      array_tmp(k) := array(j);
      j := j + 1;
      k := k + 1;
    end loop;
  
    --數組拷貝
    for i in p .. r loop
      array(i) := array_tmp(i);
    end loop;
  end merge;

begin
  -- 初始化
  array(1) := 8;
  array(2) := 1;
  array(3) := 2;
  array(4) := 7;
  array(5) := 4;
  array(6) := 6;
  array(7) := 3;
  array(8) := 9;
  array(9) := 5;

end plsql_algorithm;
---測試腳本
begin
  plsql_algorithm.init_array;
  plsql_algorithm.print_array;
  plsql_algorithm.selectionSort;
  plsql_algorithm.bubbleSort;
  plsql_algorithm.insertSort;
  plsql_algorithm.quickSort;
  plsql_algorithm.mergeSort;
  plsql_algorithm.print_array;
end;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章