算法学习(一) -- 基本算法

## 1.插入排序

插入排序法的基本思路:同样以案例来说明,还是以$arr = array(2,6,3,9),由大到小排序。

实现原理:插入排序的思想有点像打扑克抓牌的时候,我们插入扑克牌的做法。想象一下,抓牌时,我们都是把抓到的牌按顺序放在手中。因此每抓一张新牌,我们都将其插入到已有的排好序的手牌当中,注意体会刚才的那句话。也就是说,插入排序的思想是,将新来的元素按顺序放入一个已有的有序序列当中。

代码规律分析:
array(23,34,12,56,43,98,89)
注意下面括号中元素插入的位置,和比较的方法
23,(34)  ,12,56,43,98,89  第一次大循环:$[1]与$[0]比;
(12),23,34  ,56,43,98,89  第二次大循环:$[2]与$[1]比,$[1]与$[0]比;
12,23,34,(56)  ,43,98,89  第三次大循环:$[3]与$[2]比,$[2]与$[1]比,$[1]与$[0]比;
12,23,34,(43),56  ,98,89  ...
12,23,34,43,56,(98)  ,89  ...
12,23,34,43,56,(89),98  ...

```
<?php
    $arr = Array(23,34,12,56,43,98,89);
    public function charu(&$arr){
        //第一层,从第二个元素开始,一共进行n-1次循环
        for($i=1;$i<count($arr);$i++){
            //第二层,将第i个元素插入到左侧相应的位置
            for($j=$i;$j>0;$j--){
                //从第i个元素开始,与左侧元素依次比较,最小元素不断左移,直到结束
                if($arr[$j]<$arr[$j-1]){
                    //满足条件,两个元素交换位置
                    $insertVal = $arr[$j];
                    $arr[$j] = $arr[$j-1];
                    $arr[$j-1] = $insertVal;
                }
            }
        }
        return $arr;
    }
```

## 2.选择排序

在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。

代码规律分析:
array(23,34,12,56,43,98,89)

(12)  ,34,[23],56,43,98,89  第一次大循环:选出12放在第一位置;将23放在12原位置
12,([23])  ,34,56,43,98,89  第二次大循环:选出23放在第二位置;恰好自身也在此位置
12,23,([34])  ,56,43,98,89  第三次大循环:选出34放在第二位置;恰好自身也在此位置
12,23,34,(43),  [56],98,89  第四次大循环:选出43放在第二位置;将56放在43原位置
12,23,34,43,([56])  ,98,89  ...
12,23,34,43,56,(89)  ,[98]  ...
12,23,34,43,56,89,([98])    ...

```
<?php
    $arr = Array(23,34,12,56,43,98,89);
    public function xuanze($arr){
        //定义进行交换的变量
        $temp=0;
        for($i=0;$i<count($arr)-1;$i++){
            //假设$i就是最小值
            $valmin=$arr[$i];
            //记录最小值的下标
            $minkey=$i;
            for($j=$i+1;$j<count($arr);$j++){
                //最小值大于后面的数就进行交换,并且记录下相应的下标
                if($valmin>$arr[$j]){
                    $valmin=$arr[$j];
                    $minkey=$j;
                }
            }
            //将第i个元素和最小元素进行位置交换
            $temp=$arr[$i];
            $arr[$i]=$arr[$minkey];
            $arr[$minkey]=$temp;
        }
        return $arr;
    }
```

## 3.冒泡排序

冒泡排序的思想很简单,就是以此比较相邻的元素大小,将小的前移,大的后移,就像水中的气泡一样,最小的元素经过几次移动,会最终浮到水面上。

代码规律分析:
array(23,34,12,56,43,98,89)

23,34,12,56,43,[89,98]  第一次小循环:89和98比较,交换位置
23,34,12,56,[43,89],98  第二次小循环:43和89比较,不用换位置
23,34,12,[43,56],89,98  第三次小循环:56和43比较,交换位置
23,34,[12,43],56,89,98  ...
23,[12,34],43,56,89,98  ...
[12,23],34,43,56,89,98  ...

至此第一次大循环结束,做小的元素已经移到做左侧,按照同样原理进行第二次大循环.就像上面的列子,不用完整的循环n-1次,所以我们可以引入flag标记,进行优化.
```
<?php
    $arr = Array(23,34,12,56,43,98,89);
    public function maopao($arr)
    {
        $count = count($arr);
        //第一层循环开始
        for($i=1; $i<$count; $i++)
        {
            //本趟排序开始前,交换标志应为假
            $flag = false;    
            //第二层循环,使右侧最小的元素移到最左侧
            for($j=$count-1;$j>=$i;$j--)
            {
                if($arr[$j]<$arr[$j-1])//交换记录
                {//如果是从大到小的话,只要在这里的判断改成if($arr[$j]>$arr[$j-1])就可以了
                    $x=$arr[$j];
                    $arr[$j]=$arr[$j-1];
                    $arr[$j-1]=$x;
                    //发生了交换,故将交换标志置为真
                    $flag = true;
                }
            }
            //本趟排序未发生交换,提前终止算法
            if(! $flag)
                return $arr;
        }
    }
```

## 4.快速排序

所谓快速排序,就是在$arr数组中任意取一个值作为中间值,然后将这个值与数组内其他所有元素相比较,比这个值小的放到左边,比这个值大的放到这个值的右边, 此时完成一趟排序.以此类推,再将这个值左边的数进行上述排序,同样对右边的数进行上述排序.直到将所有的值都比较完.

首先使用快速排序的理念就需要使用递归,说到递归,就是用函数自己调用自己,逐层深入,最后将拿到的值返回的思想.
下面我们来看,首先我们需要自定义一个函数quick(),让此函数自己调用自己.
这里中间值我们用$arr[0],这个是随意取的,不是必须的,
为了让大家思路清晰,我们先定义两个空数组,就相当于两个杯子,
让$arr[0]与数组内所有的值进行比较,比$arr[0]小的值放到第一个杯子中,比$arr[0]大的放到第二个杯子中,在程序中分别为$left和$right,
我们判断,如果给定的数组元素只有一个或为空,此数组将被quick函数返回,不再执行下面的内容,
接下来我们对数组进行遍历,并用遍历出来的值分别与$arr[0]进行比较,比$arr[0]小的值存入$left数组,比$arr[0]大的的值存入$right数组,此时完成一趟排序,
接下来再对$left数组和$right数组进行同样的操作,也就是调用函数自己,将$left数组和$right数组传入,直到$left数组或$right数组的数组元素为一个时,不再调用自己,直接返回,
最后将左边的数组,$arr[0],$right数组合并,即可得到最终的排序结果.

```
<?php
    $arr = Array(23,34,12,56,43,98,89);
    public function kuaisu($arr){
        $left = array();
        $right = array();
        if(count($arr)<=1){
            return $arr;
        }
        for($i=1;$i<count($arr);$i++){
            if($arr[0]>$arr[$i]){
                $left[] = $arr[$i];
            }else{
                $right[] = $arr[$i];
            }
        }
        $left = kuaisu($left);
        $right = kuaisu($right);
        return array_merge($left,array($arr[0]),$right);
    }
?>
```

时间: 2024-10-12 13:13:57

算法学习(一) -- 基本算法的相关文章

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前

经典算法学习之贪心算法

贪心算法也是用来求解最优化问题的,相比较动态规划很多问题使用贪心算法更为简单和高效,但是并不是所有的最优化问题都可以使用贪心算法来解决. 贪心算法就是在每个决策点都做出在当时看来最佳的选择. 贪心算法的设计步骤: 1.将最优化问题转换为:对其做出一次选择之后,只剩下一个问题需要求解的形式(动态规划会留下多个问题需要求解) 2.证明做出贪心选择之后,原问题总是存在最优解,即贪心算法总是安全的 3.证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最

[算法学习笔记]排序算法——堆排序

堆排序 堆排序(heapsort)也是一种相对高效的排序方法,堆排序的时间复杂度为O(n lgn),同时堆排序使用了一种名为堆的数据结构进行管理. 二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树.二叉堆满足堆特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 如上图显示,(a)是一个二叉堆(最大堆), (b)是这个二叉堆在数组中的存储形式. 通过给个一个节点的下标i, 很容易计算出其父节点,左右子节点的的下标,为了方便,

算法学习之排序算法(三)(选择排序法)

1.引言 选择排序工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. 选择排序是不稳定的排序方法.选择排序是和冒泡排序差不多的一种排序.和冒泡排序交换相连数据不一样的是,选择排序只有在确定了最小的数据之后,才会发生交换.怎么交换呢?我们可以以下面一组数据作为测试: 2, 1, 5, 4, 9 第一次排序:1, 2, 5, 4, 9 第二次排序: 1, 2, 5, 4, 9 第三次排序: 1, 2, 4, 5, 9 第四次排序:

算法学习之排序算法:插入排序(直接插入排序、折半插入排序、2-路插入排序)

引言: 插入排序作为最简单易于理解的排序算法,基本实现比较简单.本文详细介绍直接插入排序,并给出实现,简单的介绍折半插入排序,并给出2-路插入排序和表插入排序两种插入排序,但并未给出具体实现. 一.直接插入排序 直接插入排序的基本操作是将一个记录插入到已排好序的有序表中,从而得到一个新的.记录数增1的有序表. 算法描述: 步骤1.将待排序的一组记录中的第1个记录拿出来作为一组有序的记录(当然此时该组记录仅有1个记录). 步骤2.依次将待排序的一组记录中的记录拿出来插入到前面已排好序的记录中. 步

算法学习之查找算法:静态查找表(1)顺序表查找

引言: 对查找表一般的操作有:1.查询某个"特定的"数据元素是否在查找表中:2.检索某个"特定的"数据元素的各种属性:3.在查找表中插入一个数据元素:4.从查找表中删去某个数据元素. 静态查找表的操作只包括两种:1.查找某个"特定的"数据元素是否在查找表中:2.检索某个"特定的"数据元素的各种属性: 静态查找表又有四种表现形式:顺序表的查找.有序表的查找.静态树的查找.索引顺序表的查找. 静态查找涉及的关键字类型和数据元素类型

算法学习之排序算法:堆排序

要了解堆排序,首先要了解堆的概念,因为本文主要研究堆排序的算法,此处对数据结构堆只是给出概念:n个元素的序列{k1,k2,...kn},当且仅当满足如下关系时,称之为堆. k[i] <= k[2i]且k[i] <= k[2i+1] (或 k[i] >= k[2i]且k[i] >= k[2i+1]) 比如:序列96.83.27.38.11.09(或12.36.24.85.47.30.53.91)都是堆. 如果将堆对应的一维数组看成是一个二叉树,则堆的含义表明:完全二叉树中所有非终端结

算法学习之排序算法:归并排序

"归并"的含义是将两个或两个以上的有序表组合成一个新的有序表.无论是顺序存储还是链表存储结构,都可在O(m+n)的时间量级上实现. 归并排序又是一类不同的排序方法.假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到n/2个为2或1的有序子序列:再两两归并,....... ,如此重复,直至得到一个长度为n的有序序列为止. 初始关键字:[49]   [38]   [65]   [97]   [76]   [13]   [27] A       A

算法学习之排序算法:选择排序

选择排序:每一趟在n-i+1(i=1,2,...,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录. 一.简单选择排序 一趟选择排序操作: 通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之. 对L[1...n]中记录进行简单选择排序的算法为:令i从1至n-1,进行n-1趟选择操作.简单选择排序过程中,所需进行记录移动的操作次数较少,然而,无论记录的初始排列如何,所需关键字间的比较次数相同.因此,总的时间复杂度为O(n^2)

算法学习之排序算法:快速排序

快速排序:快速排序是对冒泡排序的一种改进.它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. 一趟快速排序的具体做法: 1.附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey. 2.首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录互相交换. 3.从low所指位置起向后搜索,找到第一个关键字大于piv