交换排序

交换排序是指在排序过程当中,经过待排序记录序列中元素间关键字的比较,将数据元素进行交换来达到排序目的的方法,主要包括冒泡排序和快速排序。git

源码:https://github.com/fangyz/myDataStructuregithub

/*
冒泡排序的基本思想是对全部相邻记录的关键字进行比较,若是a[j]>a[j+1]则将其交换,最终达到有序化。其处理步骤以下:
(1)首先将整个待排序的记录分为有序区和无序区,初始状态有序区为空无序区则为整个待排序的记录。
(2)对无序区从前日后依次将相邻记录的关键字进行比较,若逆序则进行交换,从而使得较大的数据元素右移,这样最终造成有序序列。
经过上面的步骤能够发现,每一次冒泡排序都将无序区中最大的数据元素移到有序区的最右边。而且,对于含n个数据元素的数据序列,最多须要通过n-1趟冒泡排序。
*/
void BubbleSort(int* a,int length)
{
    if (a == NULL || length <= 0)
        return;
    int i, j,temp;
    for (i = length - 1; i > 0; i--){
        for (j = 0; j <i; j++){
            if (a[j]>a[j + 1]){
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

//若是一次循环中,没有进行数据交换,那么就说明序列已经有序。
void BetterBubbleSort(int* a, int length){
    if (a == NULL || length <= 0)
        return;
    int i, j, temp;
    bool isChanged=false;
    for (i = length - 1; i > 0; i--){
        isChanged = false;
        for (j = 0; j <i; j++){
            if (a[j]>a[j + 1]){
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
                isChanged = true;
            }
        }
        if (isChanged == false)
            break;
    }
}
//更好的冒泡排序
void BestBubbleSort(int *a, int length)
{
    int i, j;
    int temp;
    bool isChange;
    int lastMove;
    if (a == NULL || length <= 0)
        return;
    for (i = length - 1; i>0; i--)
    {
        isChange = false;
        for (j = 0; j<i; j++)            //一次执行将最大的数交换到最后面
        {
            if (a[j + 1]<a[j])
            {
                temp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = temp;
                isChange = true;       //优化点1:若是一次循环中没有数进行交换那说明已经有序了
                lastMove = j;           //优化点2:里面的for执行完毕后, 说明j到i之间的数据已经有序了,j之前的数据可能还不是有序的。
            }
        }
        if (isChange == false)
            break;
        i = lastMove + 1;
  } }

 冒泡排序是一种稳定的排序方法,由于只有在大于后一个数的状况下才进行交换。冒泡排序最好状况比较次数为n-1,移动次数仅为0,此时数据元素自己就是有序序列。最坏状况下比较次数为n*(n-1)/2,移动次数为3n(n-1)/2,平均时间复杂度为O(n^2)。接下来是快速排序。数组

/*
快速排序,能够看到它的时间复杂度主要集中在外面的while循环,这个循环的做用是进行比较找到一个位置s将数组分为0~s和s~length,也就是说快速排序的时间复杂度集中在划分区域上。
在划分区域时,首先就算划分了区域,但仍是要对这一整个数组进行比较,比较的次数是一个n阶函数,接下来重点就是划分的次数了。
最好状况下若是每次都是划分的中间的区域,那么划分次数为lbn,最坏状况下若是每次划分有一个区域是空的,那将会划分n-1次,故时间复杂度最坏O(n^2),最好是O(lbn)。
至于为何平均时间复杂度为O(nlbn)课本上写了一大堆计算公式然而暂时并无看懂。。。。
*/
void QuickSort(int *a, int start, int end)
{
    if (a == NULL || start < 0 || (start>=end))
        return;
    int s = start, e = end - 1;
    int index;
    int value = a[s];
    while (s < e){
        //必定要注意这个地方加=,由于若是不加的话,就是死循环了。
        //这个地方还有一点要注意,那就是要加上s<e,由于条件是大于或等于,那么这时有可能e会小于s。
        while (a[e]>=value&&s<e)
            e--;
        //如今执行到这个地方说明a[e]<value了,因此要让a[s]=a[e],a[e]=value,可是这里只对a[s]进行了赋值,
        //缘由是在循环中,让a[s]=a[e]后,接下来的while循环可以继续执行,当遇到a[s]>value时,此时进行替换的是a[e],即将大的数放到e这个地方。
        //这样能够发现让a[s]=a[e]后就可让s向前增长,当s增长到a[s]>value时便让a[e]=a[s],这样下一次while循环中a[e]便大于value了额,e就能够向后减小了。
        a[s] =a[e];
        while (a[s] <= value&&s<e)
            s++;
        a[e] = a[s];
        //咱们还能够发现每次执行到这个地方的时候,数组中有2个重复值,
        //那就是a[e]==a[s]>value,若是不知足s<e跳出循环那就要让a[s]=value。
    }
    a[s] = value;
    if (s < end - 1)
        QuickSort(a, s + 1, end);
    if (s>start + 1)
        QuickSort(a, start, s);
}
相关文章
相关标签/搜索