交换排序-冒泡排序 快速排序

目录

3.1 冒泡排序

3.2 快速排序

Hoare版本快速排序

挖坑法快速排序

前后指针法快速排序

快速排序优化-三数取中法

快速排序非递归


3.1 冒泡排序

思想:升序情况下:左边大于右边就进行交换,每一次把最大的放在最后一位。

void Swap(int* p1, int* p2){int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void BubbleSort(int* a, int n){//int a[] = {6,7,2,1,9,4};int end = n;//end后方均有序while (end) {int flag = 1;//假设已经排序成功for (int i = 0; i < n-1; i++) {if(a[i] > a[i+1]){flag = 0;//发生交换就说明无序Swap(&a[i], &a[i+1]);}}if(flag == 1) break;//说明没有发生交换——》已经有序//跳出循环end--;}
}

3.2 快速排序

Hoare版本快速排序

Hoare版本快速排序基本思想:取一值为key(一般取第一个数为key),在利用左右指针(双指针法),先右指针(right)找比key小的数,再左指针(left)找比key大的数据。如果找到了就交换左右指针的数据,当左右指针相遇的时候,就将相遇的数据与key进行交换,完成一次排序。接着对key的左边部分进行排序,方法与前相同,再对key右边排序,方法与前相同。由此可见,这是一个递归。

以接下来数组排序为例

int a[] = {9,5,6,3,15,13,32,18};

代码如下:

intPartSort(int* a,int left,int right){int key = left;//左找大 右找小while (left < right) {//右找小while (left < right && a[right] >= a[key]) {right--;}//左找大while (left < right && a[left] <= a[key]) {left++;}//交换左右指针数据Swap(&a[left], &a[right]);}//交换key值Swap(&a[key], &a[left]);return left;
}voidQuickSort(int* a,int left,int right){if(left >= right){return;}int key = PartSort(a, left, right);QuickSort(a, left, key-1);QuickSort(a, key+1, right);
}

Hoare版本问题分析

1⃣️ 对于key值,一般取首元素作为key值,当然也可以使用最后元素作为key值,需要注意的是,当使用首元素作为key值的时候,left一定取在首元素(即key所在位置)位置,如果不在则会出现以下情况

2⃣ ️当left指针和right指针移动的时候,一定要包含等于情况。如果不等于则出现以下情况 

 

3⃣ 递归结束条件分析,为什么是left >= right,就返回?

当二分下去后只剩一个数或者一个数都没有的时候就是有序,无需排序。如果只有等于,当某边为空的时候,此时传过来的key值为0,且key = left 那么传到下一个递归区间就变成了【0,-1】显然不和规矩,因此必须加 > 。

if(left >= right){return;
}️

挖坑法快速排序

挖坑法快速排序与Hoare版本的快速排序相比没有效率上的优化。

其基本思想是:从数据中随机选出一值为key,记录key的值,而该值的位置也是挖坑法中的坑(hole),接着利用左右指针,left在数组第一位,right在最后一位,两边向中间走,此时并没有规定谁先走,即可以left先走也可以right先走。我们假设right先走,先right找小(比key小),找到之后用right所指的数值覆盖hole的数值,再更新hole的位置到right上;再left走,找比key大的数值,找到之后,用left所指的数值覆盖hole的数值,再更新hole的位置到left上,与此反复直到两指针相遇,第一趟排序结束

//快速排序3⃣️-挖坑法
int PartSort_DigHole(int* a, int left, int right){int hole = left;int key = a[left];while (left < right) {//右找小while (left < right && a[right] >= key) {right--;}int ahole = a[hole];a[hole] = a[right];hole = right;//左找大while (left < right && a[left] <= key) {left++;}ahole = a[hole];a[hole] = a[left];hole = left;}a[hole] = key;return hole;}
void QuickSort_DigHole(int* a, int left, int right){if(left >= right){return;}int hole = PartSort_DigHole(a,left,right);QuickSort_DigHole(a,left,hole-1);QuickSort_DigHole(a,hole+1,right);
}

前后指针法快速排序

前后指针法快速排序,在效率上和挖坑法和Hoare快速排序效率所差无几。

其基本思想为:定义一个值为key(一般选第一个值为key),定义前指针(prev)后指针(cur)。先cur指针找比key小的数据,找到了就停下,在prev找比key大的数据,找到了就停下,交换前后指针数据。继续移动cur指针,直到cur指针超出排序个数(数组范围),交换prev与key的位置,完成一次排序,在如前两个方法一样进行递归排序。

以下是代码优化版

//快速排序2⃣️ 双指针法
void QuickSort2(int* a, int left, int right){int prev = left;int cur = left+1;int keyi = left;if(left >= right){return;}while (cur <= right) {//++prev != cur) 解决了自身交换的问题if(a[cur] < a[keyi] && ++prev != cur){Swap(&a[cur], &a[prev]);}cur++;}Swap(&a[prev], &a[keyi]);keyi = prev;//[left,keyi-1] key [keyi+1,right]QuickSort2(a,left,keyi-1);QuickSort2(a, keyi+1, right);//写递归一定要有出口
}

快速排序优化-三数取中法

取中的是key的位置不再是首元素,而是中间(首元素下标和尾元素下表之和的一半),确保数据存在大量数据或者有序情况下进行优化。

int GetMidi(int* a, int left, int right){int mid = (left + right)/2;if(a[left] < a[mid]){if(a[left] > a[right]){return left;}else if(a[right] > a[mid]){return mid;}else{return right;}}else{//a[left] > a[mid]if(a[right] < a[mid]){return mid;}else if (a[right] > a[left]){return left;}else{return right;}}
}//快速排序1 右找小 左找大
// 时间复杂度:O(N*logN)
// 什么情况快排最坏:有序/接近有序 ->O(N^2)
// 但是如果加上随机选key或者三数取中选key,最坏情况不会出现,所以这里不看最坏
// 小区间优化
// 面试让你手撕快排,不要管三数取中和小区间优化
// Hoare
void QuickSort1(int* a, int left, int right){// 区间只有一个值或者不存在就是最小子问题if(left >= right) return;//1⃣️随机取keyi
//    srand((unsigned int)time(NULL));
//    int randi = rand()%(right-left+1);
//    randi += left;
//    Swap(&a[randi], &a[left]);//2⃣️三数取中法int keymid = GetMidi(a,left,right);Swap(&a[keymid], &a[left]);int keyi = left;int begin = left;int end = right;while (left < right) {//右边找小while (left < right && a[right]  >= a[keyi]) {--right;}//左边找大while (left < right && a[left] <= a[keyi]) {++left;}Swap(&a[left], &a[right]);}Swap(&a[left], &a[keyi]);keyi = left;QuickSort1(a,begin,keyi-1);QuickSort1(a,keyi+1,end);
}

快速排序非递归

//
//  Stack.h
//  栈
//
//  Created by 南毅 on 2024/2/15.
//#ifndef Stack_h
#define Stack_h#include <stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>#endif /* Stack_h */typedef int STDataType;typedef struct Stack{STDataType *a;int top;int capacity;
}ST;void STInit(ST* ps);
void STDestroy(ST* ps);void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
STDataType STTop(ST* ps);
int STSize(ST* ps);
bool STEmpty(ST* ps);//
//  Stack.c
//  栈
//
//  Created by 南毅 on 2024/2/15.
//#include "Stack.h"
void STInit(ST* ps){assert(ps);ps->a = NULL;ps->top = ps->capacity = 0 ;
}void STDestory(ST* ps){assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void STPush(ST* ps, STDataType x){assert(ps);if(ps->top==ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;STDataType* tmp = realloc(ps->a, newcapacity * sizeof(STDataType));if(tmp == NULL){perror("relloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top++] = x;}void STPop(ST* ps){assert(ps);assert(!STEmpty(ps));ps->top--;
}STDataType STTop(ST* ps){assert(ps);assert(!STEmpty(ps));return ps->a[ps->top-1];
}int STSize(ST* ps){assert(ps);return ps->top;
}bool STEmpty(ST*ps){assert(ps);return ps->top==0;
}
//快速排序 非递归
void QuickSortNonR(int* a, int left, int right){ST st;STInit(&st);STPush(&st, right);STPush(&st, left);while (!STEmpty(&st)) {int begin = STTop(&st);STPop(&st);int end = STTop(&st);STPop(&st);//单躺排序int prev = begin;int cur = begin+1;int keyi = begin;while (cur <= end) {//++prev != cur) 解决了自身交换的问题if(a[cur] < a[keyi] && ++prev != cur){Swap(&a[cur], &a[prev]);}cur++;}Swap(&a[prev], &a[keyi]);keyi = prev;//[begin,keyi-1] keyi [keyi+1,end]if(keyi+1 < end){STPush(&st, end);STPush(&st, keyi+1);}if(begin < keyi-1){STPush(&st, keyi-1);STPush(&st, begin);}}//STDestroy(&st);
}

快速排序的时间复杂度为O(N\times log_{2}{N}),空间复杂度为O(log_{2}{N}),属于不稳定算法

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

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

相关文章

微信小程序:6.事件

什么事事件 事件就是渲染层到逻辑层的通讯方式&#xff0c;比如提交表单&#xff0c;按钮点击都可以看作一个事件。 小程序中常用的事件 事件对象属性列表 当事件回调时&#xff0c;会收到一个事件对象event&#xff0c;他详细属性如夏表所示&#xff1a; target和curren…

web(微博发布案例)

示例&#xff1a; 1、检测空白内容 2、发布内容 html: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta …

本地Windows主机,使用pycharm通过wsl的ubuntu来创建django项目

Windows主机在pycharm中通过wsl的ubuntu来创建django项目 需求&#xff1a;在windows主机中创建python项目再转接到linux服务器中运行&#xff0c;有点麻烦。【特别是存放日志文件或其他文件路径时需要修改为linux中的路径】 1&#xff1a;我的是windows主机 2&#xff1a;有…

【uniapp/ucharts】采用 uniapp 框架的 h5 应用使用 ucharts(没有 uni_modules)

这种情况无法直接从 dcloud 平台上一键下载导入&#xff0c;所以应该在官网推荐的 git 仓库去单独下载&#xff1a; https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6/qiun-data-charts(%E9%9D%9Euni_modules) 下载的文件是如图所示的路径&…

跳出框架:Facebook的创新策略与社交影响

1. 引言 在数字化时代&#xff0c;社交媒体如同一面镜子&#xff0c;反映出我们社会的多元性和变革。Facebook&#xff0c;作为这面镜子中最明亮的一个&#xff0c;不仅改变了人们的日常生活&#xff0c;更深刻地塑造了社交、文化和经济的面貌。本文将深入探讨Facebook的创新策…

DRF JWT认证进阶

JWT认证进阶 【0】准备工作 &#xff08;1&#xff09;模型准备 模型准备&#xff08;继承django的auth_user表&#xff09; from django.db import models from django.contrib.auth.models import AbstractUserclass UserInfo(AbstractUser):mobile models.CharField(ma…

Grafana系列 | Grafana监控TDengine库数据 |Grafana自定义Dashboard

开始前可以去grafana官网看看dashboard文档 https://grafana.com/docs/grafana/latest/dashboards 本文主要是监控TDengine库数据 目录 一、TDengine介绍二、Grafana监控TDengine数据三、Grafana自定义Dashboard 监控TDengine库数据1、grafana 变量2、添加变量3、配置panel 一…

ArcGIS批量寻找图层要素中的空洞

空洞指的是图层中被要素包围所形成的没有被要素覆盖的地方&#xff0c;当图层要素数量非常庞大时&#xff0c;寻找这些空洞就不能一个一个的通过目测去寻找了&#xff0c;需要通过使用工具来实现这一目标。 一、【要素转线】工具 利用【要素转线】工具可以将空洞同图层要素处于…

CARLA (I)--Ubuntu20.04 服务器安装 CARLA_0.9.13服务端和客户端详细步骤

目录 0. 说明0.1 应用场景&#xff1a;0.2 本文动机&#xff1a; 1. 准备工作2. 安装 CARLA 服务端软件【远程服务器】3. 安装 CARLA 客户端【远程服务器】3.1 .egg 文件安装&#xff1a;3.2 .whl 文件安装&#xff1a;3.3 从Pypi下载Python package 4. 运行服务端程序5. 运行客…

Eudic欧路词典for Mac:专业英语学习工具

Eudic欧路词典for Mac&#xff0c;作为专为Mac用户设计的英语学习工具&#xff0c;凭借其简捷高效的特点&#xff0c;成为众多英语学习者不可或缺的助手。 Eudic欧路词典for Mac v4.6.4激活版下载 这款词典整合了多个权威词典资源&#xff0c;如牛津、柯林斯、朗文等&#xff0…

Unreal Engine添加UGameInstanceSubsystem子类

点击C类文件夹&#xff0c;在右边的区域点击鼠标右键&#xff0c;在弹出的菜单中选择“新建C类”在弹出的菜单中选中“显示所有类”&#xff0c;选择GameInstanceSubsystem作为父类, 点击“下一步”按钮输入子类名称“UVRVIUOnlineGameSubsystem”&#xff0c;选择插件作为新类…

elasticsearch-8.1.0安装记录

目录 零、版本说明一、安装二、使用客户端访问 零、版本说明 centos [rootnode1 ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)elasticsearch elasticsearch-8.1.0-linux-x86_64一、安装 systemctl stop firewalld.servicesystemctl disable firewal…