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

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

引言

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

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

    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;分而治之

C#流和文件

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

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

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

C#中window窗体和控件

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

C#常用的控件

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

C#绘图及图像

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

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…

mark

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

C语言的进阶-指针的应用

指针的应用 #include <stdio.h> void swap(int *p,int *q); int main() {int a 5;int b 8;swap(&a,&b);printf("a%d,b%d\n",a,b);return 0; }void swap(int *p,int *q) {int t *p;*p *q;*q t; }函数只能返回一个值&#xff01; 可以通过参数返回多…

C语言进阶-指针与数组

C语言进阶-指针与数组 q可以改变指向的内容&#xff0c;但不能改变指向的地址 p可以改变指向地址&#xff0c;但不能改变指向内容

发布文章测试

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

C语言进阶-指针运算

C语言进阶-指针运算 #include <stdio.h>int main() {char a[] {0,1,2,3,4,5,6,7,8,9};char *p a;printf("p%d\n",p);printf("p1%d\n",p1);int b[] {0,1,2,3,4,5,6,7,8,9};int *q b;printf("q%d\n",q);printf("q1%d\n",q1);r…

C语言进阶-动态内存分配

C语言进阶-动态内存分配 #include <stdio.h> #include<stdlib.h>int main() {int number;int *a;int i;printf("请输入数组的数量");scanf("%d",&number);//int a[number];a(int*)malloc(number*sizeof(int));//开辟数组的大小for(i 0;i&…

测测

编辑 1.多喝水 2.清黑头&#xff0c;一周做一次角质&#xff0c;一个月做一次小气泡 3.防晒 无论春夏秋冬 4.少吃辣&#xff0c;多喝柠檬水 5.早上护肤步骤&#xff1a;洁面-爽肤水-眼霜-精华-面霜-防晒 6.晚上护肤步骤&#xff1a;卸妆-洁面-水-眼霜-精华-面霜 7.一周三…

QT输出出现乱码的解决

QT输出出现乱码的解决

测试图片外链MD

11111 11111111111111111111111111111 555555555

测试阿里云HTML

一直在说事件&#xff0c;那么事件到底是指什么&#xff1f;这里所说的事件是指手指按下(down)、移动(move)、抬起(up)此为一个事件集合或者说是事件序列&#xff0c;从手指接触屏幕开始到手指离开屏幕结束。所以本篇所说的事件序列或者事件集合是指从手指刚接触屏幕到离开屏幕…