笔记二:计数排序、选择排序、冒泡排序、插入排序

计数排序

1、 名次 :所谓名次,通俗理解即为该元素在序列中排行老几的意思。

2.、如何求名次:依次对每一个元素进行比较,若排在自己(该元素)前面的元素比自己大,则前面的元素在排行计数上加1,反之则自己加1。

3、利用附加数组的计数排序:根据自身名次重新整理一份排序序列存储在附加数组中,然后将附加数组值拷贝到原序列中。

1)代码:

template<typename T> void SortClass<T>::rank(T a[], int n, int r[])
{
    //给数组a[0: n-1]的n个元素排名次
    //结果在r[0: n-1]中返回
    for (int i = 0; i < n; i++)
        r[i] = 0;

    //比较所有元素,每次比较中较大元素计数器加1
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            if (a[j] <= a[i])
            {
                ++r[i];
            }
            else
            {
                ++r[j];
            }
}//rank

template<typename T> void SortClass<T>::rearrange(T a[], int n)
{
    T *u = new T[n];        //临时数组,存储排序元素
    int *r = new int[n];    //存储数组元素名次
    rank(a, n, r);

    for (int i = 0; i < n; i++)
        u[r[i]] = a[i];

    for (int i = 0; i < n; i++)
        a[i] = u[i];

    delete [] u;
    delete[] r;

}//rearrange

2)运行:

3)时间复杂度分析:在求名次rank()操作中,针对第i个元素,比较的次数为i次,因此总的比较次数为:1+2+3+…+(n-1)=(n-1)n/2次。在rearrange()中有2次for循环进行赋值操作,总的移动次数是2n。两者相加,得出附加数组的计数排序时间复杂度为:(n-1)n/2+2n =O(n2)(注:2为n的上标)

4、原地排序:所谓原地排序就是指在对序列元素进行名次计算之后,根据名次调整原序列的顺序,不借助附加数组。

1)思路:假设第一个元素a[0]的名次r[0]=3,那么,a[0]的值应该交换到下标为3的位置,即a[0]与a[3]交换。由于元素位置交换了,那么相应的,元素对应名次也要交换。停止交换的前提是a[0]元素对应的r[0]正好为0,则此时a[0]才是正确的元素。对其他位置元素,同理。

2 ) 代码:

template<typename T> void SortClass<T>::selfrearrange(T a[], int n)
{
    int *r = new int[n];    //存储数组元素名次
    rank(a, n, r);

    for (int i = 0; i < n; i++)
        while (i != r[i])       //当i == r[i]时,表明名次对应的下标存储元素正确
        {
            int tmp = r[i];
            swap(a[i], a[tmp]); //元素交换
            swap(r[i], r[tmp]); //排名交换
        }

    delete[] r;
}//selfrearrange

3)运行:

4)时间复杂度分析:名次比较次数:1+2+3+…+(n-1)=(n-1)n/2次。交换次数:当序列有序时,交换0次,当序列无序时,由于每次交换,至少使一个元素交换到正确位置,那么对任意一个元素而言,最多的交换次序是(n-1)次,在这(n-1)次交换中,其他元素也被交换正确,故最多的交换次数为(n-1)次。原地重排最坏的时间复杂度为:(n-1)n/2+(n-1)=O(n2)。


选择排序

1、定义:第一次遍历序列,找出最大元素,将该元素排到末尾去;第二次遍历序列,找出次最大元素,将该元素排到末尾前一位置去;同理,继续下去,直到最后一个元素为止。

2、思路:

3、基础选择排序:按照2中思路进行设计

1)代码:

template<typename T> void SortClass<T>::selectionSort(T a[], int n)
{
    for (int i = n - 1; i > 0; i--)     //移动的目标位置
    {
        int indexOfMax = 0;
        for (int j = 0; j < i; j++)         //找最大元素
            if (a[indexOfMax] < a[j])
                indexOfMax = j;

        swap(a[i], a[indexOfMax]);      //将最大值移到目标位置
    }
}//selectionSort

2)运行:

3)时间复杂度分析:在进行查找最大元素值过程中,比较次数为(n-1)n/2。一次swap()操作,实际包含3步tmp=a;a=b;b=a;,故移动次数为3(n-1)。基础选择排序的时间复杂度为(n-1)n/2+3(n-1)=O(n2)。

4、及时终止选择排序:在查找最大元素时,同时检查数组是否有序,减少不必要的迭代。

1)代码:

template<typename T> void SortClass<T>::selectionSortByOrder(T a[], int n)
{
    bool sorted = false;
    for (int i = n - 1; i > 0 && !sorted; i--)  //未排好序的情况下进行选择排序
    {
        int indexOfMax = 0;
        sorted = true;
        for (int j = 0; j < i; j++)
        if (a[indexOfMax] < a[j])
        {
            indexOfMax = j;
        }
        else
        {
            sorted = false;
        }

        swap(a[i], a[indexOfMax]);
    }
}//selectionSortByOrder

2)运行:


冒泡排序

1、定义:简单来讲,相邻元素之间的比较,若前者较大,则交换。一轮比较即为一次冒泡过程。

2、基础冒泡排序:

1)代码:

template<typename T> void SortClass<T>::bubbleSort(T a[], int n)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
                swap(a[j], a[j + 1]);
}//bubbleSort

2)运行:

3、及时终止的冒泡排序:

1)代码:

template<typename T> void SortClass<T>::bubbleSortByOrder(T a[], int n)
{
    bool sorted = true;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
            {
                swap(a[j], a[j + 1]);
                sorted = false;     //只要交换顺序,表明排序未结束
            }

        if (sorted)
            break;
    }

}//bubbleSortByOrder

2)运行:


插入排序

1、定义: 把序列第一个元素看做一个有序数组,将第2个元素按顺序插入到这个数组中,则这两个数组组成一个新的有序数组。将第3个元素插入到上述有序数组中,那么这3个有序数组又组成新的有序数组。如此,依次将后续元素插入到前面已排好的序列中,直至最后一个元素为止。

2、将要插入元素与已知排序数组进行比较,从后往前逐一比较,若该元素较小,则将有序数组中元素后移一位,直到腾出可以插入的空位即可。

3、插入排序:

1)代码:

template<typename T> void SortClass<T>::insertSort(T a[], int n)
{
    for (int i = 1; i < n; i++)
    {
        int j;
        int tmp = a[i];
        for (j = i - 1; j >= 0 && a[j] > tmp; j--)  //将大于a[i]的元素依次后移
        {
            a[j + 1] = a[j];
        }
        a[j + 1] = tmp; //将a[i]元素按顺序插入到a[0:i-1]中
    }
}//insertSort

2)运行:



附全代码:

#include<iostream>
using namespace std;

template <typename T> class SortClass
{
public:
    void rank(T a[], int n, int r[]);   //名次计算
    void rearrange(T a[], int n);       //利用附加数组计数排序
    void selfrearrange(T a[], int n);   //原地排序
    void selectionSort(T a[], int n);   //选择排序
    void selectionSortByOrder(T a[], int n);    //及时终止的选择排序
    void bubbleSort(T a[], int n);      //冒泡排序
    void bubbleSortByOrder(T a[], int n);       //及时终止的冒泡排序
    void insertSort(T a[], int n);      //插入排序
};

template<typename T> void SortClass<T>::rank(T a[], int n, int r[])
{
    //给数组a[0: n-1]的n个元素排名次
    //结果在r[0: n-1]中返回
    for (int i = 0; i < n; i++)
        r[i] = 0;

    //比较所有元素,每次比较中较大元素计数器加1
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            if (a[j] <= a[i])
            {
                ++r[i];
            }
            else
            {
                ++r[j];
            }
}//rank

template<typename T> void SortClass<T>::rearrange(T a[], int n)
{
    T *u = new T[n];        //临时数组,存储排序元素
    int *r = new int[n];    //存储数组元素名次
    rank(a, n, r);

    for (int i = 0; i < n; i++)
        u[r[i]] = a[i];

    for (int i = 0; i < n; i++)
        a[i] = u[i];

    delete [] u;
    delete[] r;

}//rearrange

template<typename T> void SortClass<T>::selfrearrange(T a[], int n)
{
    int *r = new int[n];    //存储数组元素名次
    rank(a, n, r);

    for (int i = 0; i < n; i++)
        while (i != r[i])       //当i == r[i]时,表明名次对应的下标存储元素正确
        {
            int tmp = r[i];
            swap(a[i], a[tmp]); //元素交换
            swap(r[i], r[tmp]); //排名交换
        }

    delete[] r;
}//selfrearrange

template<typename T> void SortClass<T>::selectionSort(T a[], int n)
{
    for (int i = n - 1; i > 0; i--)     //移动的目标位置
    {
        int indexOfMax = 0;
        for (int j = 0; j < i; j++)         //找最大元素
            if (a[indexOfMax] < a[j])
                indexOfMax = j;

        swap(a[i], a[indexOfMax]);      //将最大值移到目标位置
    }
}//selectionSort

template<typename T> void SortClass<T>::selectionSortByOrder(T a[], int n)
{
    bool sorted = false;
    for (int i = n - 1; i > 0 && !sorted; i--)  //未排好序的情况下进行选择排序
    {
        int indexOfMax = 0;
        sorted = true;
        for (int j = 0; j < i; j++)
        if (a[indexOfMax] < a[j])
        {
            indexOfMax = j;
        }
        else
        {
            sorted = false;
        }

        swap(a[i], a[indexOfMax]);
    }
}//selectionSortByOrder

template<typename T> void SortClass<T>::bubbleSort(T a[], int n)
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
                swap(a[j], a[j + 1]);
}//bubbleSort

template<typename T> void SortClass<T>::bubbleSortByOrder(T a[], int n)
{
    bool sorted = true;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - 1; j++)
            if (a[j] > a[j + 1])
            {
                swap(a[j], a[j + 1]);
                sorted = false;     //只要交换顺序,表明排序未结束
            }

        if (sorted)
            break;
    }

}//bubbleSortByOrder

template<typename T> void SortClass<T>::insertSort(T a[], int n)
{
    for (int i = 1; i < n; i++)
    {
        int j;
        int tmp = a[i];
        for (j = i - 1; j >= 0 && a[j] > tmp; j--)  //将大于a[i]的元素依次后移
        {
            a[j + 1] = a[j];
        }
        a[j + 1] = tmp; //将a[i]元素按顺序插入到a[0:i-1]中
    }
}//insertSort

int main(int argc, char *argv[])
{
    int a[6] = { 6, 5, 8, 4, 3, 1 };
    cout << "原始数组顺序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;
    SortClass<int> SClass;
    /*SClass.rearrange(a, 6);
    cout << "采用附加数组计数排序:";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.selfrearrange(a, 6);
    cout << "采用重排计数排序:    ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/ 

    /*SClass.selectionSort(a, 6);
    cout << "采用选择排序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.selectionSortByOrder(a, 6);
    cout << "采用及时终止选择排序:";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.bubbleSort(a, 6);
    cout << "采用冒泡排序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    /*SClass.bubbleSortByOrder(a, 6);
    cout << "采用及时终止冒泡排序:";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;*/

    SClass.insertSort(a, 6);
    cout << "采用插入排序:        ";
    for (int i = 0; i < 6; i++)
        cout << a[i] << " ";
    cout << endl;

    return 0;
}
时间: 2024-10-13 00:07:13

笔记二:计数排序、选择排序、冒泡排序、插入排序的相关文章

01. Java的经典排序--选择排序--冒泡排序--折半查找(二分查找)

Java的经典排序--选择排序--冒泡排序--折半查找 选择排序 选择排序 3 2 1 5 8 0 1 3 2 5 8 1 1 2 3 5 8 2 1 2 3 5 8 3 1 2 3 5 8 public static void main(String[] args) { int[] arr={3,2,1,5,8}; selectSort(arr); for(int i = 0 ; i < arr.length ; i ++){ System.out.println(arr[i]) ; } }

算法大神之路----排序(选择排序法)

选择排序法,顾名思义,就是把特定的数据选择出来进行排序. 选择排序法有两种方式 在所有的数据中,当由大到小排序,那么就将最大值放到第一个位置 如果由小到大排序,那么就将最小值放到第一个位置 以由小到大排序举例,当排序时候,扫描整个数据,拿第一个依次与其他做比较,如果其他数据比第一个大,或者相等,那么就不交换,如果其他数据比第一个数小,那么就交换二者的位置,扫描结束后,则从第二个数开始,依次扫描. 方法分析 无论是最坏还是最好情况,甚至是平均情况下,都需要对全部数据进行扫描,找到最大或最小值,因此

算法二之树形选择排序

一.树形选择排序的基本思想 (1) 树形选择排序又称锦标赛排序(Tournament Sort),是一种按照锦标赛的思想进行选择排序的方法.首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止. (2) 树形选择排序(Tree Selection Sort),这个过程可用一棵有n个叶子结点的完全二叉树表示. 例如,图表中的二叉树表示从8个数中选出最小数的过程. 8个叶子结点到根接点中的关键字,每个非终端结点中的数均等于其左右孩子结点中较小的

Java排序算法(二):简单选择排序

[基本思想] 在要排序的一组数中.选出最小的一个数与第一个位置的数交换:然后在剩下的数中再找出最小的与第二个位置的数交换,如此循环至倒数第二个数和最后一个数比較为止. 算法关键:找到最小的那个数.并用变量记住它的下标. [java实现] public class SimpleSelectionSort { public static void main(String[] args) { int[] arr = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; System.out.p

iOS疯狂详解之排序(选择排序/插入排序)

选择排序 1.先求最小值 2.找到位置 3.把位置的数放到有序区 4.重复 for (int j = 0; j < count - 1; j++) { int minIndex = j;// 最小值的角标 for (int i = minIndex + 1; i < count; i++) { if (array[minIndex] > array[i]) { minIndex = i; } } if (minIndex != j) { // 优化 无序区的头 不是第一个 // 最小值

算法(第四版)学习笔记之java实现选择排序

选择排序步骤: 1.找到数组中参与遍历比较的所有元素中的最小元素的下标: 2.将最小元素与数组中参与遍历比较的第一个元素进行交换(如果第一个元素就是最小元素的话,那么也会进行一次交换): 3.若数组中还有需要参与遍历比较的元素,则跳转到步骤1:否则排序结束. 在算法第四版中给出的所有排序均是适用于任意实现了Comparable接口的数据类型,若要将数字作为测试用例,请勿使用基本数据类型,改用Integer等实现了Comparable接口的对象. 选择排序代码如下: /** * * @author

(二)选择排序之二:简单选择排序

选择排序分为:简答选择排序.树形选择排序.堆排序,今天来学一下简答选择排序. 具体代码如下: package com.cust.heap; /** * * 描述:简单选择排序 * @author cookie */ public class 简单选择排序 { public static void main(String[] args) { int[] array = new int[]{2,5,6,9,4,1,7}; print(array);//打印 for(int i = 0; i < ar

排序—选择排序

选择排序 排序要求:把长度为n的数组a按照从小到大的顺序进行排序. 冒泡排序思路:给定一个长度为n的数组a,循环n-1次,每次循环找出a[i]到a[n]中最小数的数,然后把该数和a[i]交换位置. 如何找出最小的数?:循环数组,逐个判断大小,把较小的数的脚标取出来,此次循环结束之后把脚标位置的数和a[i]进行交换. 排序示例: 原数组: 2.0.3.6.8.4.9.5.1.7.第1次循环排序结果: 0.2.3.6.8.4.9.5.1.7.第2次循环排序结果: 0.1.3.6.8.4.9.5.2.

数据结构——排序——选择排序算法

选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理如下.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾.以此类推,直到所有元素均排序完毕. 选择排序的主要优点与数据移动有关.如果某个元素位于正确的最终位置上,则它不会被移动.选择排序每次交换一对元素,它们当中至少有一个将被移到其最终位置上,因此对n个元素的表进行排序总共进行至多n-1次交换.在所有的完全依靠交换去移动元素的排序方

C-冒泡排序,选择排序,数组

——构造类型 ->数组 ->一维数组 ->相同类型的一组数据 ->类型修饰符--数组名—[数组的元素个数(必须是整型表达式或者是整型常量,不能是变量)] {初始化} int arr[3] = {1,2,3}; arr[1] = 5; printf("%d",arr[1]); ->数组内存的值为变量 ->使用数组的时候中括号内可以是变量 ->sizeof()是一个运算符,不是一个函数,可以计算变量或者变量修饰符占了多少个字节,也可以对数组进行计算