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;