数据结构与算法(一)——排序

虽然之前学过数据结构,但是已时隔四年,大概四月份复习了一遍,但是很多概念也是一知半解,所以重新整理知识点和运行代码的方式来巩固知识。

引言

  • 排序:是计算机程序设计中的一种重要操作,功能是将一个数据元素的任意序列重新排列成一个按关键字的有序序列

  • 根据待排序记录的存储器的不同可分为

    sort_methods

  • 各个排序算法的性能比较

    sort_algorithm_compare

冒泡排序

算法说明

冒泡排序是一种交换排序。那什么是交换排序呢?

交换排序:两两比较待排序的关键字,并交换不满足次序要求的那对数,直到整个表都满足次序要求为止。

  • 基本思想:通过相邻记录两两比较交换的方式,找到每次迭代中数据的最大值,最终达到排序的目的。

  • 算法描述

    • 首先将第一个记录的关键字与第二个记录的关键字进行比较,若为逆序(L.r[1].key>L.r[2].key),则将两个记录交换,然后比较第二个记录和第三个记录的关键字,依次类推,直到第n-1个记录和第n个记录进行比较为止。这是一趟排序。
    • 然后进行第二趟排序,对前n-1个记录进行同样的操作。重复这样的操作。
    • 直到冒泡排序在一趟拍讯中没有进行过交换记录的操作为止。

这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端,故名。

用例说明

冒泡排序

代码实现

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];
}
}
}
?>

基数排序

算法说明

代码实现

参考:

  1. 严蔚敏 等著《数据结构 C语言版》
  2. 程序员的内功——数据结构和算法系列
  3. 排序一 冒泡排序
  4. 排序二 快速排序
  5. 排序三 直接插入排序
  6. 排序四 希尔排序
  7. 排序五 简单选择排序
  8. 排序六 堆排序
  9. 排序七 归并排序
  10. 排序八 基数排序
  11. 用PHP实现的常用排序算法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/242268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP(四)——性能优化

之前基于PHP开发的过程中&#xff0c;一直没有涉及到PHP性能优化的问题&#xff0c;但是一般来说PHP性能问题占整个项目性能问题一般占30%-50%部分&#xff0c;所以说&#xff0c;这部分内容是非常重要的。下面是最近自己PHP性能优化学习的资料整理。 引言[1]PHP存在性能问题的…

C#常用的算法

C#常用的算法 遍试算法 迭代算法 递归 递归算法的基本思想&#xff1a;分而治之

kaggle使用笔记

因为参加了DCASE2018比赛的声学场景分类的子任务&#xff0c;这个比赛有个排行榜是用的kaggle来做的&#xff0c;所以在比赛中&#xff0c;用到过kaggle API&#xff0c;下面是关于kaggle的使用笔记。 kaggle 是什么&#xff1f;Kaggle是一个数据科学竞赛的平台&#xff0c;很多…

PHP简单功能的实现

检查一个变量是否为空empty功能返回值&#xff1a;若变量不存在则返回 TRUE若变量存在且其值为””、0、”0”、NULL、FALSE、 array()、var $var; 以及没有任何属性的对象&#xff0c;则返回 TURE若变量存在且值不为””、0、”0”、NULL、FALSE、 array()、var $var; 以及没有…

C#流和文件

C#流和文件 文件及文件夹管理 WinForm中的文件对话框 文件内容的读写 注册表操作

PHP操作MySQL数据库(连接、增删改操作)

MySQL 是跟 PHP 配套使用的最流行的开源数据库系统&#xff0c;我们知道MySQL是PHP的最佳搭档&#xff0c;下面是系统的总结PHP与MySQL联合使用的方法。主要是使用MySQL扩展&#xff0c;下面就通过归纳总结来提升。 MySQL概述MySQL 是一种在 Web 上使用的数据库系统。 MySQL 是…

互联网应届生四项职场生存技能

职场能力一&#xff1a;沟通力沟通力是职场最重要也是最基础的一项能力。 进入职场后&#xff0c;无论从事什么岗位都必然要用到沟通力这个能力项。沟通力有一个很重要的基石&#xff0c;就是尊重对方的时间。每一次沟通&#xff0c;双方其实都要投入很多时间和精力。只有懂得尊…

C#中程序错误的种类和程序的调试

C#中程序错误的种类 语法错误 运行错误 逻辑错误 程序调试的基本手段 然后运行 调试程序例子 例子2&#xff1a;读文件 没有找到文件 null引用就是没有进行初始化 索引超出数组界限

缓存

最近在狂补优化方面的知识&#xff0c;缓存也是优化的一大方向。之前关于缓存只是知道它的功能&#xff0c;再多不知道了&#xff0c;这里整理缓存相关的知识&#xff0c;算是优化入门吧。 相关概念缓存 是“存贮使用频繁的数据的临时地方&#xff0c;因为取原始数据的代价太大…

mysql中as用法

重命名列名或者表名。as可理解为&#xff1a;用作、当成&#xff0c;作为&#xff1b;一般是重命名列名或者表名。&#xff08;主要为了查询方便&#xff09; 重命名列。如&#xff1a;表text&#xff0c; 列 column_1,column_2 你可以写成&#xff1a; 1select column_1 as …

C#中window窗体和控件

C#中window窗体和控件 布局与事件–界面的基本问题 布局 就是拉动窗体的时候&#xff0c;按钮也在跟着变动。 事件 //简单的计算器 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; namespa…

PHP自动加载机制

概述首先&#xff0c;为什么PHP需要自动加载呢&#xff1f; 在PHP面向对象(OO)编程中&#xff0c;为了方便管理&#xff0c;我们都会把一个类写在一个单独的文件中&#xff0c;那么如果想在A类中使用B类的功能&#xff0c;就需要把B类加载到A类。对于这样的需求在最原始的时候&…

操作系统知识——互斥和死锁

银行家算法银行家算法是最有代表性的避免死锁算法&#xff0c;是Dijkstra提出的。这是由于该算法能用于银行系统现金贷款的发放而得名。 我们可以把操作系统看作是银行家&#xff0c;操作系统管理的资源相当于银行家管理的资金&#xff0c;进程向操作系统请求分配资源相当于用户…

C#常用的控件

C#常用的控件 窗体 菜单、工具栏、对话框 用户控件及控件的继承

C++输入函数的应用

最近因为找工作的事情&#xff0c;在刷一些编程题&#xff0c;也陆陆续续参加了一些笔试&#xff0c;一般编程中使用的语言是C&#xff0c;因为编程题会有时间的限制&#xff0c;C的效率最高&#xff0c;不容易出现超时的问题所以使用最多的语言就是C。 在编程中&#xff0c;其…

C#绘图及图像

C#绘图及图像 绘图的基本方法 绘图的应用

PHP开发API

引言如何使用 PHP 开发 API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09; 呢&#xff1f; 做过 API 的人应该了解&#xff0c;其实开发 API 比开发 WEB 更简洁&#xff0c;但可能逻辑更复杂&#xff0c;因为 API 其实就是数据输出&a…

热部署和热加载

2018-8-22今天入职第二天&#xff0c;看到老大在群里发了一个go热加载实现的链接&#xff0c;之前没有听说过热加载&#xff0c;所以搜索了一下&#xff0c;下面是关于热部署和热加载的相关整理。 引言在项目线上更新时&#xff0c;可能会遇到需要热部署的情况&#xff0c;虽然…

C#实现定时器

C#实现定时器 方法一 布局 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace…

HTTP请求流程

hhtp请求流程首先http是一个应用层的协议&#xff0c;在这个层的协议&#xff0c;只是一种通讯规范&#xff0c;也就是因为双方要进行通讯&#xff0c;大家要事先约定一个规范。 http请求与响应的步骤如下&#xff1a; URL解析、域名解析 输入URL的时候&#xff0c;首先浏览器会…