首页 > 编程语言 >常见的排序算法

常见的排序算法

时间:2024-09-10 16:49:48浏览次数:8  
标签:arr 元素 temp int 常见 算法 var 排序

算法分类

1、排序

  • 比较类排序

2、复杂度

相关概念

  • 稳定:如果 a 本来在 b 前面,而a = b ,排序之后 a 仍然在 b 的前面
  • 不稳定:如果 a 本来 在b的前面,而 a = b ,排序之后 a 可能在 b 的后面
  • 时间复杂度:对排序数据的总的操作数,反映当 n 变化时,操作次数呈什么变化
  • 空间复杂度: 指算法计算机内执行时所需存空间的度量,也是数据规模 n 的函数

几种常见排序(已学)

1、冒泡排序(Bubble Sort)

~~注:重复地走访序列,一次比较两个元素,如果顺序错误就交换过来,重复地进行直到没有再需要交换,也就说该数列排序完成------->这个算法的名字是因为越小的元素会经由交换慢慢“浮”到顶端

动图展示

aoKJdf.gif

代码实现

function bubbleSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len - 1; i++) {
        for (var j = 0; j < len - 1 - i; j++) {  //每次循环最大的元素都被放到最后,就不用管了
            if (arr[j] > arr[j+1]) {        // 相邻元素两两对比
                var temp = arr[j+1];        // 元素交换
                arr[j+1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    return arr;
}

课上讲的模板类写法:

template<class T>
void mySwap(T &x,T &y)
{
	T temp = x;
	x = y;
	y = temp;
}

template<class T>
void bubbldeSort(T a[],int n)
{
	int i= n-1 ;
	while(i>0){
	int lastExchange = 0;//每次都值为 0 ,如果下面的 if语句 不成立,退出循环,说明排序完成
        //(a[j]<a[j+1])都成立
	for(int j=0;j<i;j++)
	  if(a[j+1]<a[j])
	  {
	  mySwap(a[j],a[j+1]);
	  lastExchange = j;  //第一次循环这个 j = n-1,a[j+1]包括后面的数就不用管了
	  }
	  i = lastExchange;
	}
}

2、选择排序(Selection Sort)

~~注:首先在未排序序列中找到最小(大)的元素,存放到排序序列的起始位置,然后再从剩余未排序序列元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到排序完毕。

动图

aoKYo8.gif](https://imgchr.com/i/aItpqJ)

代码实现;

function selectionSort(arr) {
    var len = arr.length;
    var minIndex, temp;
    for (var i = 0; i < len - 1; i++) {
        minIndex = i; //记录未排序的第一个数,方便后面最小的数与其交换
        for (var j = i + 1; j < len; j++) {
            if (arr[j] < arr[minIndex]) {     // 寻找最小的数
                minIndex = j;                 // 将最小数的索引保存
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp; //将 i 和最小的数交换 ,然后 i 往后移一位,前面是已经排好的序列
    } 
    return arr;
} 

3、插入排序

~注:描述--->

  • 第一个元素已经排序
  • 取出下一个元素,在已经排序的元素序列中从后往前扫描
  • 如果该元素(已排序)大于新元素,将该元素移至下一个位置
  • 重复3,直到找到已排序的元素小于或等于新元素的位置
aoKNFS.gif

代码实现:

function insertionSort(arr) {
    var len = arr.length;
    var preIndex, current;
    for (var i = 1; i < len; i++) {
        preIndex = i -1; 
        current = arr[i];  //前面的数都是已经排好序的 
        while (preIndex >= 0 &&  arr[preIndex] > current) { //后面的数比前面的大就循环,如果小于或等于就停止循环,进行插入
            arr[preIndex + 1] = arr[preIndex]; //往后挪位置
            preIndex--;
        }
        arr[preIndex+1] = current;  //上面arr[preIndex]往后移了,此时arr[preIndex]为无用值,又减了一,所以要加1;
    }
    return arr;
}
//注释1:从下标为1的元素开始遍历,记作temp-->然后从temp向前遍历将元素往后挪位,直到不满足条件插入此元素

c++模板类写法:

template<class T>
void insertionSort(T a[],int n)
{
	int i,j;
	T temp;
	for(int i=1;i<n;i++)
	{
 	int j=i;
 	T temp = a[i];
	while(j>0 && temp<a[j-1])
	{
		a[j]=a[j-1]; //这里j值并没有改变,下面减去一才是要填充的位置
		j--;
	}
	a[j]=temp; //a[j-1]被移动到后面的序列去了, j-1是无用数据
	}
}
3 2 5 4 9 8 7 temp = 2
2 3 5 4 9 8 7 temp = 5
2 3 4 5 9 8 7 temp = 5
    //注释2:从下标为1开始循环(因为要j-1不能越界),如果前面的元素比temp(循环选定元素)大,说明要后退一位,以便留一个位置给temp,就这样一直后移直到找到一个数 < temp

4、计数排序

适用于在较小范围内的数字;

  • 计数排序可以不用进行比较两数大小的操作
  • 另外用一个数组记录出现数字的次数,下标表示数字,数组下标对应的元素表示该数字出现的次数
#include<bits/stdc++.h>
using namespace std;

void countSort(vector<int>& array){
   int max = array[0];
   for(int i=1;i<array.size();i++){// 找出最大值
       if(array[i]>max){
           max = array[i];
       }
   }
   vector<int> countArray(max+1); // 容量为max+1 
    for(int i=0;i<array.size();i++){
        countArray[array[i]]++;
    }

    int index = 0;// countArray下标代表数字,对应的元素值表示
    //出现的次数
    ================================
    for(int i=0;i<countArray.size();i++){
        for(int j=0;j<countArray[i];j++){
            array[index++] = i;
            // 直接修改原数组(参数)
            ================================
        }
    }
}

int main(){
    vector<int> a={4,4,6,5,3,2,8,1,7,5,6,0,10};
    countSort(a);
   for(vector<int>:: iterator it = a.begin();it!=a.end();it++ ){
       cout<<*it<<endl;
   }

    return 0;
}

5、快速排序

  • 基准元素
  • 两边向中间循环查找

双边循环

#include <iostream>
#include <vector>
#define N 10
using namespace std;
void sawp(int &a,int &b)// 交换两个数
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
void quickSort(int left,int right,vector<int> & a)
{
    if(left >= right)
    return;

    int i,j,base;
    i = left, j =right;
    base = a[left];// 基准元素
    while(i < j)
    {
        while(a[j]>=base && i < j) //i <j 基本条件
        j--;

        while(a[i]<=base && i < j)
        i++;

        if(i < j) // 有可能此时i==j
        swap(a[i],a[j]); //交换左边和右边的值,一个大于基准值,一个小于基准值

    }
    a[left] = a[i];
    a[i] = base;
    quickSort(left,i-1,a);//对剩余的部分进行快速排序
    quickSort(i+1,right,a);//
}

y总模板

#include <iostream>

using namespace std;

const int N = 1000010;

int q[N];

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
 
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }

    quick_sort(q, l, j);
    quick_sort(q, j + 1, r);
}

int main()
{
    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    quick_sort(q, 0, n - 1);

    for (int i = 0; i < n; i ++ ) printf("%d ", q[i]);

    return 0;
}

单边循环>


#include <iostream>
#include <vector>
#define N 10
using namespace std;
void sawp(int &a, int &b) { // 交换两个数
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void quickSort(vector<int> &a, int L, int R) {

    if(L>=R){
        return; // 递归结束条件
    }
	// L,R表示起始和终点下标
	int p = a[L];
	int mark = L;
    
	for (int i = L + 1; i <= R; i++) {
        
		if (a[i] < p) {
            cout<<p<<"  >  "<<a[i]<<endl;
            cout<<"mark值为"<<mark<<endl;
			mark++;
            cout<<"mark值为"<<mark<<endl;
			swap(a[mark], a[i]); //此时mark表示a[mark]>p,把小的
			// 提到前面来
          
   
		}
	}
    
	swap(a[mark], a[L]);
    
	quickSort(a, L, mark - 1);
	quickSort(a, mark + 1, R);
}

int main() {
	vector<int> a = {4,7,3,5,6,2,8,1};
	quickSort(a, 0, a.size() - 1);
	for (int i = 0; i < a.size(); i++) {
		cout << a[i] << " ";
	}
	return 0;
}

标签:arr,元素,temp,int,常见,算法,var,排序
From: https://www.cnblogs.com/ddja/p/18406654

相关文章

  • 【南京工业大学主办 | IEEE出版,有ISBN号,往届均已见刊并完成EI, Scopus检索】第八届控
    重要信息大会网站:https://ais.cn/u/aQzEnm【投稿参会】时间地点:2024年11月1-3日| 中国·南京截稿时间:以官网信息为准出版信息:IEEE出版(ISBN:979-8-3315-2888-1)收录检索类型:IEEEXplore,EI,Scopus组织单位:征稿主题1)算法和数据结构2)人工智能3)电气系统4)......
  • 简单的算法总结
    算法笔记欧几里得算法求最大公约数~又称辗转相除法,求两数的最大公约数gcd(a,b)=gcd(b,a%b)一般代码递归形式intgcd(inta,intb){ returnb?gcd(b,a%b):a;}迭代形式intgcd(inta,intb){ while(1) { if(b==0)returna; inttemp=a%b; a=b;......
  • 每日算法随笔:反转链表 II
    明白了!下面我将基于你给的两种方法来详细解释题解,并展示每一步的变化过程。题解:反转链表II这道题要求我们反转链表中从第left个节点到第right个节点的部分,返回反转后的链表。我们会使用两种方法:递归和迭代。示例解析示例1:输入:head=[1,2,3,4,5],left=2,ri......
  • 洛谷题单指南-常见优化技巧-P2880 [USACO07JAN] Balanced Lineup G
    原题链接:https://www.luogu.com.cn/problem/P2880题意解读:在若干个不定长区间里,求区间最大值与最小值之差解题思路:对于区间求最值,通常有几种方式:1、暴力法,通过枚举所有的区间来计算区间最值2、单调队列,针对区间长度固定的情况3、ST表,针对区间长度不固定且元素不会发生改变的......
  • 每日算法随笔:反转链表
    题解:反转链表这道题目要求我们将一个单链表进行反转,返回反转后的链表。链表的反转可以通过迭代和递归两种方法来实现。下面我们将详细解释这两种方法,并通过例子演示每一步的变化过程。方法一:迭代法思路:我们用三个指针来完成链表的反转:prev表示前一个节点,curr表示当前节......
  • 【Py/Java/C++三种语言OD独家2024E卷真题】20天拿下华为OD笔试之【回溯】2024E-字符串
    可上欧弟OJ系统练习华子OD、大厂真题绿色聊天软件戳od1441了解算法冲刺训练(备注【CSDN】否则不通过)文章目录相关推荐阅读题目描述与示例题目描述输入描述输出描述示例一输入输出说明示例二输入输出说明解题思路代码pythonjavacpp时空复杂度华为OD算法/大厂面......
  • 常见的Java课程设计/毕业设计选题
    从网上整理收集了常见的java系统设计源码,可以用于课程作业或者毕业设计。技术栈:java/springboot/mysql/js/vue1.基于java的家政预约网站系统平台采用B/S结构,后端采用主流的Springboot框架进行开发,前端采用主流的Vue.js进行开发。整个平台包括前台和后台两个部分。前台功能包括:首页......
  • *Python*机器学习算法——神经网络和深度学习
            神经网络和深度学习是现代机器学习的重要组成部分,它们在图像识别、语音识别、自然语言处理等多个领域取得了显著的成功。本文将详细介绍神经网络和深度学习的基本函数概念,并通过一个简单的例子来展示如何使用Python和Keras库构建一个神经网络模型。1、前置库......
  • 莫队算法
    莫队算法普通莫队形式:给定一个长度为\(n\)的序列,有\(q\)次询问,每次询问给出\(l,r\),问区间\([l,r]\)的答案。要求:询问必须离线,且从区间\([l,r]\)转移到区间\([l+1,r],[l-1,r],[l,r+1],[l,r-1]\)的时间复杂度是\(O(1)\)的。做法:关于\(l\)对询问分块,块长为\(T\),......
  • 聚类算法 0基础小白也能懂(附代码)
    聚类算法0基础小白也能懂(附代码)原文链接啥是聚类算法聚类(Clustering)是最常见的无监督学习算法,它指的是按照某个特定标准(如距离)把一个数据集分割成不同的类或簇,使得同一个簇内的数据对象的相似性尽可能大,同时不在同一个簇中的数据对象的差异性也尽可能地大。也即聚类后同一类......