虽然之前学过数据结构,但是已时隔四年,大概四月份复习了一遍,但是很多概念也是一知半解,所以重新整理知识点和运行代码的方式来巩固知识。
引言 冒泡排序 算法说明 冒泡排序 是一种交换排序。那什么是交换排序呢?
交换排序:两两比较待排序的关键字,并交换不满足次序要求的那对数,直到整个表都满足次序要求为止。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端,故名。
用例说明
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49); $res = BubbleSort($list); print_r($res); function BubbleSort($list) { $len = count($list); for ($i = 0; $i < $len; $i++) { for ($j = $len-1; $j > $i; $j--) { if ($list[$j-1] > $list[$j]) { swap($list, $j-1, $j); $bChange = true; } } } echo $k; return $list; } function swap(&$list, $i, $j) { $temp = $list[$i]; $list[$i] = $list[$j]; $list[$j] = $temp; } ?>
输出:
1 2 3 4 5 6 7 8 9 10 11 Array ( [0] => 13 [1] => 27 [2] => 38 [3] => 49 [4] => 49 [5] => 65 [6] => 76 [7] => 97 )
快速排序 算法说明 快速排序 是冒泡排序的改进,整个快速排序的过程是一个递归的过程 。
基本思想 :通过一趟排序将待排记录分割成独立两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续记性排序,以达到整个序列有序。
算法描述 :
一趟快速排序的步骤:设两个指针low和high,设枢轴记录的关键字为pivotkey; 先从high所指向的位置向前搜索 找到第一个小于pivotkey 的记录和枢轴记录互相交换; 然后从low所指向的位置向后搜索 找到第一个大于pivotkey 的记录和枢轴记录互相交换; 重复前面两步骤,知道low=high为止。 取当前的pivotkey记录所在的位置(枢轴位置),将整个记录分割为两个子序列,分别进行快速排序; 直到待排序列中只有一个记录为止。 用例说明
代码实现 先将枢轴记录暂存在r[0]的位置上,排序过程只作r[row]或者r[high]的单向移动,知道一趟排序结束后,再将枢轴记录移至正确的位置上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include<iostream> using namespace std; // 声明快排函数 void quickSort(int a[],int,int); int main() { int array[]={34,65,12,43,67,5,78,10,3,70},k; int len=sizeof(array)/sizeof(int); cout<<"The orginal arrayare:"<<endl; for(k=0;k<len;k++) cout<<array[k]<<","; cout<<endl; quickSort(array,0,len-1); cout<<"The sorted arrayare:"<<endl; for(k=0;k<len;k++) cout<<array[k]<<","; cout<<endl; system("pause"); return 0; } void quickSort(int s[], int l, int r) { if (l< r) { int i = l, j = r, x = s[l]; while (i < j) { while(i < j && s[j]>= x) // 从右向左找第一个小于x的数 j--; if(i < j) s[i++] = s[j]; while(i < j && s[i]< x) // 从左向右找第一个大于等于x的数 i++; if(i < j) s[j--] = s[i]; } s[i] = x; quickSort(s, l, i - 1); // 递归调用 quickSort(s, i + 1, r); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49);//这个用例输出的是null //$list = array(9, 1, 5, 8, 3, 7, 4, 6, 2);//这个用例测试结果是对的 $res = QuickSort($list); print_r($res); print_r($list); function QuickSort($list) { $len = count($list); Qsort($list, 0, $len-1); return $list; } function Qsort(&$list, $low, $high) { if ($low < $high) { $pivot = Partition($list, $low, $high); Qsort($list, $low, $pivot-1); Qsort($list, $pivot+1, $high); } } function Partition(&$list, $low, $high) { $pvalue = $list[$low]; while ($low < $high) { while ($low < $high && $list[$high] > $pvalue) { $high--; } swap($list, $low, $high); while ($low < $high && $list[$low] < $pvalue) { $low++; } swap($list, $low, $high); } return $low; } function swap(&$list, $i, $j) { $temp = $list[$i]; $list[$i] = $list[$j]; $list[$j] = $temp; } ?>
直接插入排序 算法说明 直接插入排序 是一种最简单的排序方法,它的基本操作是将一个记录仪插入到已排好序的有序表中,从而得到一个新的、记录数增1的有序表。
算法描述 :
先取代排序序列中的第一个记录作为一个有序序列; 取第二个记录,在这个有序序列依次查找比它小的最大关键字,将该记录插入到查找的关键字位置后面; 取第i个记录按同种方法插入到当前有序序列; 将最后一个记录插入,即可完成排序。 用例说明
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49); $res = InsertionSort($list); print_r($res); function InsertionSort($list){ $len = count($list); for ($i = 1; $i < $len; $i++) { if ($list[$i] < $list[$i-1]) { $target = $list[$i]; for($j = $i-1; $j >= 0 && $list[$j] >= $target; $j--) { $list[$j+1] = $list[$j]; } $list[$j+1] = $target; } } return $list; } ?>
希尔排序 算法说明 希尔排序 又称“缩小增量排序”,也属于插入排序类方法,但时间效率更高。希尔排序的一个特点:子序列的构成不是简单地“逐段分割”,而是将相隔某个“增量”的记录组成一个子序列。
算法描述 :
将整个待排序序列分割成若干个子序列 对每个子序列分别进行直接插入排序 待每个子序列中的记录有序时,再缩小增量重新分割子序列,重复上一步操作,直到增量为1,进行最后一次排序后即完成排序。 这个算法,主要是通过增量划分子序列,使序列基本有序,减小插入排序的复杂度。
需注意的是,到目前为止,尚未有人求得一种最好的增量序列,但是也有一些局部结论。增量序列可以用多种取法,但需注意:应使增量序列中的值没有除1以外的公因数,并且最后一个增量值必须等于1 。
用例说明
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49); $res = ShellSort($list); print_r($res); function ShellSort($list) { $len = count($list); $increment = $len; do { $increment = floor($increment/3) + 1; for ($i = $increment; $i < $len; $i++) { if ($list[$i] < $list[$i-$increment]) { $target = $list[$i]; for ($j = $i-$increment; $j >= 0 && $list[$j] > $target; $j -= $increment) { $list[$j+$increment] = $list[$j]; } $list[$j+$increment] = $target; } } }while($increment > 1); return $list; } ?>
简单选择排序 算法说明 简单选择排序 是一种选择排序。每一趟在n-i+1(i=1,2,…,n-1)个记录中选择关键字最小的记录作为有序序列的第i个记录。
算法描述
先从n个记录(待排序列)中找到最小的关键字,作为第一个记录 随后在剩下的n-1(n-i+1)子序列中再寻找最小关键字,作为第2(i)个记录 依次类推,直到剩下最后的一个记录(即最大关键字)为止。 用例说明
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49); $res = SelectionSort($list); print_r($res); function SelectionSort($list) { $len = count($list); for ($i = 0; $i < $len; $i++) { $min = $i; for ($j = $i; $j < $len; $j++) { if ($list[$min] > $list[$j]) { $min = $j; } } if ($min != $i) { swap($list, $min, $i); } } return $list; } function swap(&$list, $i, $j) { $temp = $list[$i]; $list[$i] = $list[$j]; $list[$j] = $temp; } ?>
树形选择排序 算法说明 树形选择排序 ,又称“锦标赛排序”,是一种按照锦标赛的思想进行选择排序的方法,是对简单选择排序的一种改进。
算法描述
首先对n个记录的关键字进行两两比较,选出较小者 然后在其[n/2]个较小者之间再进行两两比较,再选出较小者 如此重复,知道选出最小关键字的记录为止 将最小关键字输出,然后根据关系的可传递性,选出次小关键字,依次输出,直到输出所有的记录。 用例说明
堆排序 堆 :一棵顺序存储的完全二叉树。
小顶堆 :其中每个结点的关键字都不大于其孩子结点的关键字,这样的堆称为小顶堆 (小根堆)。
大顶堆 :其中每个结点的关键字都不小于其孩子结点的关键字,这样的堆称为大顶堆 (大根堆)。
举例来说
对于n个元素的序列{R0, R1, … , Rn}当且仅当满足下列关系之一时,称之为堆:
(1) Ri <= R2i+1 且 Ri <= R2i+2 (小顶堆)
(2) Ri >= R2i+1 且 Ri >= R2i+2 (大顶堆)
其中i=1,2,…,n/2向下取整
算法说明 根据初始数组去构造初始堆(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。 每次交换第一个和最后一个元素,输出最后一个元素(最大值),然后把剩下元素重新调整为大顶堆。 当输出完最后一个元素后,这个数组已经是按照从小到大的顺序排列了。 用例说明
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49); $res = HeapSort($list); print_r($res); function HeapSort($list) { $len = count($list); for ($i = floor(($len-2)/2); $i >= 0; $i--) { createHeap($list, $i, $len-1); } for ($i = $len-1; $i >=0 ; $i--) { swap($list, $i, 0); createHeap($list, 0, $i-1); } return $list; } function createHeap(&$list, $i, $j) { $target = $list[$i]; for ($m=$i*2+1; $m <= $j ; $m = $m*2+1) { if ($m < $j && $list[$m] < $list[$m+1]) { $m++; } if ($target > $list[$m]) { break; } $list[$i] = $list[$m]; $i = $m; } $list[$i] = $target; } function swap(&$list, $i, $j) { $temp = $list[$i]; $list[$i] = $list[$j]; $list[$j] = $temp; }
归并排序 算法说明 归并排序 是将两个或者两个以上的有序表组合成一个新的有序表。
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法 (Divide and Conquer)的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并 。
算法描述
将待排序序列R[0…n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表; 将这些有序序列再次归并,得到n/4个长度为4的有序序列 如此反复进行下去,最后得到一个长度为n的有序序列。 归并排序其实要做两件事 :
(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。
用例说明
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?php $list = array(49, 38, 65, 97, 76, 13, 27, 49); $res = MergeSort($list); print_r($res); function MergeSort(&$list) { $len = count($list); $res = array(); Msort($list, $res, 0, $len-1); return $res; } function MSort(&$list, &$res, $s, $t) { if ($s == $t) { $res[$s] = $list[$s]; }else{ $m = floor(($s + $t)/2); $temp = array(); //新建一个空数组 MSort($list, $temp, $s, $m); MSort($list, $temp, $m+1, $t); Merge($temp, $res, $s, $m, $t); } } function Merge(&$temp, &$res, $s, $m, $t) { for ($k = $s, $j = $m+1; $s <= $m && $j <= $t; $k++) { if ($temp[$s] < $temp[$j]) { $res[$k] = $temp[$s]; $s++; }else{ $res[$k] = $temp[$j]; $j++; } } if ($s <= $m) { for ($l = 0; $l <= $m-$s ; $l++) { $res[$k+$l] = $temp[$s+$l]; } } if ($j <= $t) { for ($l = 0; $l <= $t-$j ; $l++) { $res[$k+$l] = $temp[$j+$l]; } } } ?>
基数排序 算法说明 代码实现 参考: 严蔚敏 等著《数据结构 C语言版》 程序员的内功——数据结构和算法系列 排序一 冒泡排序 排序二 快速排序 排序三 直接插入排序 排序四 希尔排序 排序五 简单选择排序 排序六 堆排序 排序七 归并排序 排序八 基数排序 用PHP实现的常用排序算法