码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-04-26 19:54:39      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

计数排序

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;
}

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

标签:

原文地址:http://blog.csdn.net/u014033518/article/details/51250597

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!