php幾種常見排序演算法

來源:互聯網
上載者:User

標籤:return   時間複雜度   bre   合并   ges   時間   tin   count   ret   

<?php

//從時間上來看,快速排序和歸併排序在時間上比較有優勢,
//但是也比不上sort排序,歸併排序比較佔用記憶體!


$arr = [4,6,1,2,3,89,56,34,56,23,65];
/**
* 冒泡排序
* 它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。
* 走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成
*/
function BubbleSortq($arr)
{
$len = count($arr);
//設定一個空數組 用來接收冒出來的泡

for ($i = 1; $i < $len; $i++) //該層迴圈控制 需要冒泡的輪數
{
$flag = false; //本趟排序開始前,交換標誌應為假
//該層迴圈用來控制每輪 冒出一個數 需要比較的次數
for ($k = 0; $k < $len - $i - 1; $k++)
{
//從小到大排序
if ($arr[$k] > $arr[$k + 1])
{
$tmp = $arr[$k + 1];
$arr[$k + 1] = $arr[$k];
$arr[$k] = $tmp;
$flag = true;
}
}
if(!$flag) return $arr;
}
}

// print_r(BubbleSort($arr));

/**
* 選擇排序演算法
* 每一次從待排序的資料元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的資料元素排完。
* 選擇排序是不穩定的排序方法(比如序列[5, 5, 3]第一次就將第一個[5]與[3]交換,導致第一個5挪動到第二個5後面)
*/
function SelectSort($arr)
{
//定義進行交換的變數
$temp = 0;
for ($i = 0; $i < count($arr) - 1; $i++)
{
$minval = $arr[$i];//假設$minval就是最小的值
$minvalIndex = $i;//最小值的下標
for ($j = $i + 1; $j < count($arr); $j++)
{
if ($minval > $arr[$j])//從小到大排列
{
$minval = $arr[$j];//找最小值
$minvalIndex = $j;
}
}
$temp = $arr[$i];
$arr[$i] = $arr[$minvalIndex];
$arr[$minvalIndex] = $temp;
}
return $arr;
}

// print_r(SelectSort($arr));

/**
* 插入演算法
* 每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的檔案中適當位置上,直到全部插入完為止。
* 演算法適用於少量資料的排序,時間複雜度為O(n^2)。是穩定的排序方法。
*/
function insertSort($arr)//從小到大排列
{
//先預設$arr[0],已經有序,是有序表
for ($i = 1; $i < count($arr); $i++)
{
$insertval = $arr[$i];//$insertval是準備插入的數
$insertIndex = $i - 1;//有序表中準備比較的數下標
while ($insertIndex >= 0 && $insertval < $arr[$insertIndex])
{
$arr[$insertIndex + 1] = $arr[$insertIndex];//將數組往後挪
$insertIndex--;//將下標往前挪,準備與前一個進行比較
}
if ($insertIndex + 1 !== $i)
{
$arr[$insertIndex + 1] = $insertval;
}
}
return $arr;
}
// print_r(insertSort($arr));


/*
* 快速排序法
* 通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,
* 然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
*/
function quickSort($arr)
{
//判斷是否為數組
if (is_array($arr))
{
return false;
}
//如果數組長度為1直接返回
if (!isset($arr[1]))
{
return $arr;
}

$mid = $arr[0]; //擷取一個用於分割的關鍵字,一般是首個元素
$leftArray = array();
$rightArray = array();
foreach ($arr as $v)
{
if ($v > $mid)
{
$rightArray[] = $v; //把比$mid大的數放到一個數組裡
}
if($v < $mid)
{
$leftArray[] = $v; //把比$mid小的數放到另一個數組裡
}
}
$leftArray = quickSort($leftArray); //把比較小的數組再一次進行分割
$leftArray[] = $mid; //把分割的元素加到小的數組後面,不能忘了它哦
$rightArray = quickSort($rightArray); //把比較大的數組再一次進行分割
return array_merge($leftArray,$rightArray); //組合兩個結果
}
// print_r(quickSort($arr));

 

/**
* 歸併排序
* 歸併排序是指將兩個或兩個以上有序的數列(或有序表),合并成一個仍然有序的數列(或有序表)。
* 這樣的排序方法經常用於多個有序的資料檔案歸併成一個有序的資料檔案。
*/
function mergeSort(&$arr)
{
$len = count($arr);//求出數組長度
mSort($arr,0,$len - 1);
return $arr;
}
//實際實現歸併排序的程式
function mSort(&$arr,$left,$right)
{
if ($left < $right)
{
//說明子序列記憶體在多餘1個的元素,那麼需要拆分,分別排序,
//合并計算拆分的位置,長度/2 取整
$center = floor(($left + $right) / 2);
//遞迴調用對左邊進行再次排序
mSort($arr, $left, $center);
//遞迴調用對右邊進行再次排序
mSort($arr, $center + 1, $right);
//合并排序結果
mergeArray($arr, $left, $center, $right);
}
}
//講兩個有序數組合并成一個有序數組
function mergeArray(&$arr, $left, $center, $right)
{
//設定兩個起始位置標記
$a_i = $left;
$b_i = $center + 1;
while ($a_i <= $center && $b_i <= $right)
{
//當數組A和數組B都沒有越界時
if ($arr[$a_i] < $arr[$b_i])
{
$temp[] = $arr[$a_i++];
}
else
{
$temp[] = $arr[$b_i++];
}
}
//判斷 數組A內的元素是否都用完了,沒有的話將其全部插入到C數組內
while ($a_i <= $center)
{
$temp[] = $arr[$a_i++];
}
//判斷 數組A內的元素是否都用完了,沒有的話將其全部插入到C數組內
while ($b_i <= $right)
{
$temp[] = $arr[$b_i++];
}
//將$arrC內排序好的部分,寫入到$arr內
for ($i = 0, $len = count($temp); $i < $len; $i++)
{
$arr[$left + $i] = $temp[$i];
}
}

// print_r(mergeSort($arr));


/*
* 希爾排序
* 將數組按指定步長分隔成若干子序列,然後分別對子序列進行排序(在這是直接)
*/
function shellSort($arr)
{
$len = count($arr);
$k = floor($len / 2);
while ($k > 0)
{
for ($i = 0; $i < $k; $i++)
{
for ($j = $i; $j < $len, ($j + $k) < $len; $j = $j + $k)
{
if ($arr[$j] > $arr[$j + $k])
{
$tmp = $arr[$j + $k];
$arr[$j + $k] = $arr[$j];
$arr[$j] = $tmp;
}
}
}
$k = floor($k / 2);
}
return $arr;
}

// print_r(shellSort($arr));

/*
*堆排序
*調整子堆的為大根堆的過程,$s為子堆的根的位置,$m為堆最後一個元素位置
*/


function heapAdjust(&$arr, $s, $m)
{
$tmp = $arr[$s];
// 在調整為大根堆的過程中可能會影響左子堆或右子堆
// for迴圈的作用是要保證子堆也是大根堆
for ($j = 2*$s + 1; $j <= $m; $j = 2*$j + 1)
{
// 找到根節點的左右孩子中的最大者,然後用這個最大者與根節點比較,
// 若大則進行調整,否則符合大根堆的 特點跳出迴圈
if ($j < $m && $arr[$j] < $arr[$j + 1])
{
$j++;
}
if ($tmp >= $arr[$j] )
{
break;
}
$arr[$s] = $arr[$j];
$s = $j;
}
$arr[$s] = $tmp;
}
// 堆排序
function heapSort($arr)
{
$len = count($arr);
// 依次從子堆開始調整堆為大根堆
for ($i = floor($len / 2 - 1); $i >= 0; $i--)
{
heapAdjust($arr, $i, $len - 1);
}
// 依次把根節點調換至最後一個位置,再次調整堆為大根堆,找到次最大值,
// 依次類推得到一個有序數組
for ($n = $len - 1; $n > 0; $n--)
{
$tmp = $arr[$n];
$arr[$n] = $arr[0];
$arr[0] = $tmp;
heapAdjust($arr, 0, $n - 1);
}
return $arr;
}
print_r(heapSort($arr));

php幾種常見排序演算法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.