1.问题来源

在刷题是遇到字符串相关问题中使用 strcmp()函数。

在函数比较过程中有使用 排序函数 Sort(beg,end,comp),其中comp这一项理解不是很彻底。

#include <vector>
#include <cstring>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<const char*> cats {"Heathcliff", "Snagglepuss", "Hobbes", "Garfield"};
std::sort(cats.begin(), cats.end(), [](const char *strA, const char *strB) { return std::strcmp(strA, strB) < 0; }); // 注意这个comp的写法
for (const char *cat : cats) {
std::cout << cat << '\n';
}
}
/*
*输出:
*Garfield
Heathcliff
Hobbes
Snagglepuss
*/
/*
* [](const char *strA, const char *strB) { return std::strcmp(strA, strB) < 0; } 不是很理解 ,为什么在前面还需要 [] 来实现?
*/

当然也可以定义一个comp变量函数

std::sort(begin(),end(),compare);
bool compare (const char* strA,const char* strB )
{
return std::strcmp(strA,strB)<0;
}

2.comp的定义

Elements are compared using the given binary comparison function comp.

这一块的内容还是需要继续学习

3.各种排序算法的实现

排序算法列表:

0.Bubble Sort 冒泡排序

1.Selection Sort 选择排序

2.Insertion Sort 插入排序

3.Shell Sort 希尔排序

4.Merge Sort 归并排序

5.Heap Sort 堆排序

6.Quick Sort 快速排序

0.BubbleSort

  • 冒泡排序实现,两两比较关键字
// 基础实现
void BubbleSort(vector<int>& nums){
int i,j;
int len=nums.size();
for(i=0;i<len;++i){
// 后面向前进行循环
// 最小值冒泡到顶端
for(j=len-2;j>=i;--j){
if(nums[j]>nums[j+1])
{
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
}
}
} // 改进版本
void BubbleSort2(vector<int>& nums){
int i,j;
int len=nums.size();
bool flag=true;
for(i=0;i<len &&flag;i++){
flag=false;
for(j=len-2;j>=i;--j){
if(nums[j]>nums[j+1]){
// 有数据交换
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
flag=true;
}
}
}
}

1.Selection Sort

  • 选择排序的基本思路:

在未排序的数组中找到最小的元素与未排序数组的第一个元素进行交换

void SelectionSort(vector<int>& nums)
{
for(int i=0;i<nums.size();++i)
{
int min_index=i;
for(int j=i+1;j<nums.size();++j) // 遍历维排序数组
{
if(nums[j]<nums[min_index])
min_index=j; // 找到最小的元素的下标
}
int temp=nums[i]; // 交换
nums[i]=nums[min_index];
nums[min_index]=temp;
}
}
/*
* 时间复杂度: O(n^2) 空间复杂度 : O(1)
* in_palce order ?
*/

2.InsertionSort

  • 插入排序的基本思路:

与要插入的元素之前的元素进行对比,元素要不断的向右进行移动

void InsertionSort(vector<int>& nums)
{
for(int i=1;i<nums.size();++i)
{
int temp=a[i]; // 要插入的元素
int j=i-1;
while(j>=0 && temp<a[j]) // 之前的元素相对比,向右移动
{
a[j+1]=a[j];
j--;
}
a[j+1]=temp;
}
}
/*
* 时间复杂度 O(n^2)
*/

同样的解题思路,java代码看着更舒服

public class Insertion
{
public static void sort(Comparable[] a)
{
// ascending
int N=a.length;
for(int i=1;i<N;i++)
{
// 将 a[i]插入到 a[i-1],a[i-2]中
for(int j=i;j>0 && less(a[j],a[j-1]);j--)
{
exch(a,j,j-1);
}
}
} }

3.ShellSort

希尔排序的主要思路:

希尔排序是基于插入排序的快速排序

1.交换不相邻的元素对数组的局部进行排序(最重要的就是间隔的选择)

2.最终使用插入排序将局部有序的数组排序

/* 至今无法解释其算法性能
* 这个算法熟悉知道一下就好
*/
public class Shell
{
public static void sort(Comparable[] a)
{
int N=a.length();
int h=1; // 定义这个间隔 gap
while(h<N/3)
h=h*3+1;
while(h>=1)
{
for(int i=h;i<N;i++)
{
for(int j=i;j>0 && less(a[j],a[j-h]);j-=h)
exch(a,j,j-h);
}
h=h/3; // 缩小gap继续进行交换
}
}
}

Cplusplus implemented

void ShellSort(int a[],int len)
{
for(int gap=len/2;gap>0;gap/=2)
{
for(int i=gap;i<len;i++)
{
int j=i-gap;
while(j>=0 && a[j]>a[j+gap])
{
swap(a[j],a[j+gap]);
j-=gap;
}
}
}
}

4.MergeSort

归并排序的主要思路:

现将数组递归的分成两半分别排序,再将结果归并起来

将数组递归的分成最小,按照有序的方式归并起来

/*
* 所需的时间复杂度O(NlogN)
*/
// 两个数组的原地归并 public class Merge
{
private static Comparable[] aux;
public static void sort(Comparable[] a)
{
aux=new Comparable[a.length]; // 分配空间
sort(a,0,a.length-1);
}
private static void sort(Comparable[] a,int lo,int hi) // a[lo,hi]进行排序
{
if(hi<lo)
return;
int mid=lo+(hi-lo)/2;
sort(a,lo,mid);
sort(a,mid+1,hi);
merge(a,lo,mid,hi);
}
public static void merge(Comparable[]a,int lo,int mid,int hi)
{
int i=lo,j=mid+1;
for(int k=lo;k<hi;++k)
aux[k]=a[k]; // 将数组完全复制到一个临时数组中
for(int k=lo;k<=hi;k++)
{
if(i>mid) a[k]=aux[j++]; // 分别对应左半数组和右半数组用尽的情况
else if (j>hi) a[k]=aux[i++];
else if (less(a[i],a[j])) a[k]=aux[i++];
else a[k]=aux[j++];
}
}
}

5.HeapSort

堆排序

  • 经典而又优雅的排序算法

堆排序思路:

基于(二叉堆的数据结构)优先队列实现,优先队列是利用二叉堆来实现的。

1.根据堆的构造,现将堆构造出来

2.根据 sink 算法实现堆的下沉排序 最后实现有序

sink 算法,将堆有序的最后一个元素交换到顶点,从顶点开始下沉操作

// 堆的有序化
private void swim (int k)
{
while(k>1 && less(k/2,k))
{
exch(k/2,k);
k=k/2;
}
}
private void sink(int k)
{
while(2*k<=N) // 保证还有字节点可以下沉比较
{
int j=2*k;
if(j<N && less(j,j+1)) j++; // 找到字节点中最大的进行交换
if(!less(k,j)) break;
exch(k,j);
k=j;
}
} public class Heap { // This class should not be instantiated.
private Heap() { } /**
* Rearranges the array in ascending order, using the natural order.
*/
public static void sort(Comparable[] pq) {
int n = pq.length;
for (int k = n/2; k >= 1; k--)
sink(pq, k, n); // 第一步实现堆的有序 2N项比较
while (n > 1) { // 2NlgN次比较
exch(pq, 1, n--); // 交换顶点和尾结点的元素
sink(pq, 1, n); // 进行下沉
}
} /***************************************************************************
* Helper functions to restore the heap invariant.
***************************************************************************/ private static void sink(Comparable[] pq, int k, int n) {
while (2*k <= n) {
int j = 2*k;
if (j < n && less(pq, j, j+1)) j++;
if (!less(pq, k, j)) break;
exch(pq, k, j);
k = j;
}
}
}

6.QuickSort

快速排序的思路:

最重要的是找到切分元素,将数组分成左右两个部分 (切分元素的选取)

切分后进行双指针比较,根据与切分元素的比较,将元素进行交换位置

将左右两个部分进行排序

/*
* 快速排序是原地排序
* 分而治之的排序方法
* 时间复杂度 O(NlgN)
*/ public class Quick
{
public static void sort(Comparable[] a)
{
StdRandom.shuffle(a); // 重新打乱混淆一下数组,这样对切分元素的选择更理想
sort(a,0,a.length-1);
}
private static void sort(Comparable[]a,int lo,int hi)
{
if(hi<=lo) // 进行错误判断
return;
int j=partition(a,lo,hi); // get 切分元素
sort(a,lo,j-1); // 左右两边数组进行排序
sort(a,j+1,hi);
}
/* 切分的实现*/
private static int partition(Comparable[]a ,int lo,int hi)
{
// 将数组进行分离 a[lo,...i-1] a[i+1...hi]
int i=lo,j=hi+1;
Comparable v=a[lo]; // 确定切分元素
while(true)
{
while(less(a[++i],v)) if(i==hi) break; // 到不小于V,应该在右侧的元素
while(less(v,a[--j])) if(j==lo) break; // 小于 V,应该在左侧的元素
if(i>=j) break;
exch(a,i,j);
}
exch(a,lo,j); // 将v 放入正确的位置,切分值放到a[j]中
/* a[lo,..j-1]<=a[j]<=a[j+1..hi] */
return j;
}
}

选择排序、快速排序、归并排序、堆排序、快速排序实现及Sort()函数使用的更多相关文章

  1. php基础排序算法 冒泡排序 选择排序 插入排序 归并排序 快速排序

    <?php$arr=array(12,25,56,1,75,13,58,99,22);//冒泡排序function sortnum($arr){    $num=count($arr);    ...

  2. 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)

    排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...

  3. Java冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序

    冒泡排序   冒泡排序是一种简单的排序算法.它重复地走访过要排序地数列,一次比较两个元素,如果它们地顺序错误就把它们交换过来.走访数列地工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成. ...

  4. java实现冒泡排序,选择排序,插入排序,快速排序(简洁版)及性能测试

    1.冒泡排序是排序里面最简单的了,但性能也最差,数量小的时候还可以,数量一多,是非常慢的. 它的时间复杂度是O(n*n),空间复杂度是O(1) 代码如下,很好理解. public void bubbl ...

  5. Java选择排序,插入排序,快速排序

      public class Test { public static void main(String[] args) { int a[] = { 1, 2, 3, 4, 5 }; 选择排序(a); ...

  6. 排序方法整理Java - 冒泡排序、选择排序、插入排序、快速排序

    /** * 排序方法整理 * @author zhyea * */ public class Sort { /** * 冒泡排序,从小到大. * 冒泡排序是比较相邻的两个元素,若顺序错误,则执行交换. ...

  7. 常见排序算法总结分析之选择排序与归并排序-C#实现

    本篇文章对选择排序中的简单选择排序与堆排序,以及常用的归并排序做一个总结分析. 常见排序算法总结分析之交换排序与插入排序-C#实现是排序算法总结系列的首篇文章,包含了一些概念的介绍以及交换排序(冒泡与 ...

  8. C++/C实现各种排序算法(持续更新)--冒泡排序,选择排序,归并排序

    2018 3 17 今日总结一下C++中的排序算法: 1冒泡排序 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是 ...

  9. c语言 快速排序---归并排序----堆排序

    //快速排序: #include <stdio.h> #define MAX 500000 int s[MAX]; void Q_Sort(int start,int end) { int ...

  10. 冒泡(bubblesort)、选择排序、插入排序、快速排序

    冒泡排序(bubblesort) 特点:通过换位置的方式,一直向上冒泡 package main import "fmt" func bubbleSortAsc(arrayA [] ...

随机推荐

  1. 初始SpringMVC 完整版

    初始SpringMVC 1.SpringMVC 也叫Spring Web mvc,属于表现层的框架.Spring MVC是Spring框架的一部分,是在Spring3.0后发布的. 2.Java EE ...

  2. 如何使用JSP访问MySQL数据库

    <%@page import="java.sql.*" import ="java.util.*" import ="java.io.*&quo ...

  3. mysql语句汇总

      MySQL常用命令: show databases; 显示数据库 create database name; 创建数据库 use databasename; 选择数据库 drop database ...

  4. python对数据去重处理

    我们在数据处理时,经常需要用到对重复数据进行过滤处理.  对数据去重有两种处理方式,如下: 1.对重复数据去重,并且会自动排序 使用函数  set # 列表去重 list_a = [6, 6, 5, ...

  5. 解决微信小程序开发者工具输入框焦点问题

    Windows10笔记本上运行微信小程序开发者工具,输入框(input,textarea)没有焦点,只能在真机调试,效率太低.后来发现是Window10对笔记本高分屏支持不好,要DPI缩放,导致兼容性 ...

  6. C语言编程学习打造——做题游戏

    C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...

  7. 【Java例题】2.4求函数

    4.输入x,编程试求函数 y=sin(x^2)/(1-cosx)的值. 这里的"^"表示乘方. package study; import java.util.Scanner; p ...

  8. ThreadPoolExecutor线程池的一个面试题

    问题:现有一个线程池,参数corePoolSize = 5,maximumPoolSize = 10,BlockingQueue阻塞队列长度为5,此时有4个任务同时进来,问:线程池会创建几条线程? 如 ...

  9. Xlistview_聚合菜谱大全数据

    public class MainActivity extends AppCompatActivity implements XListView.IXListViewListener{ private ...

  10. java Timer工具类实现定时器任务

    第一 schedule 方法 三个参数 按照顺序 (执行的任务方法,开始执行时间,多少时间后循环去执行)  代码可用 public class TestScheedule { public stati ...