排序算法C++程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiaoyangwm/article/details/81428062

排序算法程序

这里写图片描述

1、冒泡排序

通过对相邻数据的元素进行交换,逐步将待排序序列排成有序序列的过程。

如升序排列:

  • 扫描整个待排序序列(非整个序列,不扫描已经排好的序列)
  • 在一趟扫描中,最终必然将最大的元素排在待排序序列的末尾,这也是最大元素应该在的位置
  • 第一趟排序之后,将最大的元素排在最后一个位置,第二趟将次大的放到倒数第二个位置…
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10

//排序用的顺序表结构
typedef struct
{
    int r[MAXSIZE + 1];
    int length;
}SqList;

//交换两个值

void swap(SqList *L, int i, int j)
{
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;

}

// 冒泡排序

void Bubblesort(SqList *L)
{
    int i, j, p;
    int flag = 1;

    for (i = 1; i < L -> length && flag; i++)
    {
        flag = 0;
        for (j = L->length - 1; j >= i; j--)
        {
            if (L->r[j]>L->r[j + 1])
            {
                swap(L, j, j + 1);
                flag = 1;
            }
        }
        printf("\n\n第%d次排序结果为:\n\n", i);
        for (p = 1; p < L->length + 1; p++)
        {
            printf("%3d", L->r[p]);
        }
    }

}

int main()
{
    int x, y;
    SqList L;
    L.length = 10;

    printf("待排序的结果为:\n");
    for (x = 1; x < 11; x++)
    {
        y = rand() % 10;
        L.r[x] = y;
        printf("%3d", y);
    }

    Bubblesort(&L);

    getchar();
    return 0;
}

输出:

这里写图片描述

#include<iostream>
using namespace std;
template<typename T>
void bubble( T t[],int len)//注意模板中的参数T为参数类型,所以不能写成T[]
{
    bool flag=true;
    int i,j;
    for(i=1;i<=len-1&&flag;i++)
    {
        flag=false;
        for(j=0;j<len-i;j++)//如果外层循环是从1开始,那么内层循环j<len-i,
            //不能取等号,否则会产生下标越界,因为下面的交换判断语句为t[j]
            //与t[j+1],
        {
            if(t[j]>t[j+1])
            {
                swap(t[j],t[j+1]);
                flag=true;
            }
        }
    }
}

void main()
{
    int a[]={4,2,1,3,5,7,6};
    char x[100]={'x','y','s','a','n','c','m'};//此处必须指定数组的大小,虽然不指定也不会出错,但是当用字符去初始化一个没定义长度的字符数组时,系统不会默认在
          //末尾添加'\0',所以此时不能用strlen函数来求该字符数组的长度,而当指定数组的大小后,余下的系统自动赋值为空,即'\0'

//  int len=strlen(a);错误,strlen函数的参数为char*类型
    int len=sizeof(a)/4;
    for(int i=0;i<len;i++)
        cout<<a[i]<<' ';
    cout<<endl;
    cout<<"排序后结果为"<<endl;
    bubble(a,len);
    for(int i=0;i<len;i++)
        cout<<a[i]<<' ';
    cout<<endl;

    int str_len=strlen(x);
    for(int i=0;i<len;i++)
        cout<<x[i]<<' ';
    cout<<endl;
    cout<<"排序后结果为"<<endl;
    bubble(x,str_len);
    for(int i=0;i<len;i++)
        cout<<x[i]<<' ';
    cout<<endl;

}

2、直接插入排序

基本操作是将一个记录插入到已经排好的有序表中,从而得到一个新的、记录增1的有序表。

也就是将第一个数作为已经排好的序列,第二个数是插入其左边还是右边的情况。

#include <iostream>
#include <stdlib.h>

#define MAXSIZE 10
//排序用的顺序表结构
typedef struct
{
    int r[MAXSIZE + 1];//用于存储要排序数组,r[0]用做哨兵或临时变量
    int length;
}SqList;

//交换两个值
void swap(SqList *L, int i, int j){
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;
}

//直接插入排序

void InsertSort(SqList *L)
{
    int i, j,p;
    for (i = 2; i <= L->length; i++)
    {
        if (L->r[i] < L->r[i - 1])
        {
            L->r[0] = L->r[i];  //设置哨兵
            for (j = i - 1; L->r[j]>L->r[0]; j--)
            {
                L->r[j + 1] = L->r[j];
            }
            L->r[j + 1] = L->r[0];
        }
        printf("\n\n第%d次排序结果为:\n\n", i);
        for (p = 1; p < L->length + 1; p++)
        {
            printf("%3d", L->r[p]);
        }
    }

}

int main()
{
    int x, y;
    SqList L;
    L.length = 10;

    printf("待排序的序列为为:\n");
    for (x = 1; x < 11; x++)
    {
        y = rand() % 10;
        L.r[x] = y;
        printf("%3d", y);
    }

    InsertSort(&L);

    getchar();
    return 0;
}

输出:

这里写图片描述

3、希尔排序

基于增量“inception”对序列进行分割

第一次:inception=length/3+1,i=inception+1,将第i位和第i-inception位比较
第二次:inception=inception/3+1,i=inception+1
直到inception=1为止

#include <iostream>
#include <stdlib.h>

#define MAXSIZE 10
//排序用的顺序表结构
typedef struct
{
    int r[MAXSIZE + 1];//用于存储要排序数组,r[0]用做哨兵或临时变量
    int length;
}SqList;

//交换两个值
void swap(SqList *L, int i, int j){
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;
}

//直接插入排序

void ShellSort(SqList *L)
{
    int i, j, p;
    int increment = L->length;
    do
    {
        increment = increment / 3 + 1;
        for (i = increment + 1; i < L->length; i++)
        {
            if (L->r[i] < L->r[i - increment])
            {
                L->r[0]=L->r[i];
                for (j = i - increment; j>0 && L->r[0] < L->r[j]; j = j - increment)
                    L->r[j + increment] = L -> r[j];
                L->r[j + increment] = L->r[0];

            }
        }
        printf("\n\n第%d次排序结果为:\n\n", i-increment);
        for (p = 1; p < L->length + 1; p++)
        {
            printf("%3d", L->r[p]);
        }
    } 
    while (increment > 1);


}

int main()
{
    int x, y;
    SqList L;
    L.length = 10;

    printf("待排序的序列为为:\n");
    for (x = 1; x < 11; x++)
    {
        y = rand() % 10;
        L.r[x] = y;
        printf("%3d", y);
    }

    ShellSort(&L);

    getchar();
    return 0;
}

这里写图片描述

4、快速排序

快速排序作为和冒泡排序相同类型的排序(同为交换类排序),之所以能够被人们所熟知,是因为它解决了冒泡排序只用来对相邻两个元素进行比较,因此在互换两个相邻元素时只能消除一个逆序,而快速排序是通过两个不相邻元素的交换,来消除待排序记录中的多个逆序。即快速排序中的一趟交换可以消除多个逆序。

具体思想:

从待排序记录中选取一个记录(通常选取第一个记录,当然也可采用随机划分的方式,这样能大大提高快速排序的执行效率,如我们所熟知的在O(n)的时间复杂度内找出前k元的算法),将其关键字记为K1,然后将其余关键字小于K1的记录移到前面,而大于关键字K1的移到后面。

一趟快速排序之后,将待排序序列划分为两个子表,最后将关键字K1插到这两个子表的分界线的位置。具体实现就是用三层while循环,最外层的while循环控制该趟快速是否进行,而内层的两个while循环一个用来从左到右扫描大于该趟基准记录关键字的元素,一个用来从右到左扫描小于该趟基准记录的关键字的元素,可以用两个指针low和high指向当前从左到右和从右到左扫描的当前记录的关键字,找到一个就将其交换。

以上是一趟快速排序的思想,对上述划分后的子表重复上述过程,直至划分后的子表的长度不超过1为止。即为快速排序的思想,从定义可知快速排序是一个递归排序。

#include <iostream>
#include <stdlib.h>

#define MAXSIZE 10
//排序用的顺序表结构
typedef struct
{
    int r[MAXSIZE + 1];//用于存储要排序数组,r[0]用做哨兵或临时变量
    int length;
}SqList;

//交换两个值
void swap(SqList *L, int i, int j)
{
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;
}

void QuickSort(SqList *L);
void QSort(SqList *L, int low, int high);
int Partition(SqList *L, int low, int high);

int main()
{
    int x, y;
    SqList L;
    L.length = 10;

    printf("待排序的序列为:\n");
    for (x = 1; x < 11; x++)
    {
        y = rand() % 10;
        L.r[x] = y;
        printf("%3d", y);
    }

    QuickSort(&L);

    getchar();
    return 0;
}



//快速排序

void QuickSort(SqList *L)
{
    QSort(L, 1, L->length);

}

void QSort(SqList *L, int low, int high)
{
    int pivot,p;
    if (low < high)
    {
        pivot = Partition(L, low, high);

        QSort(L, low, pivot - 1);
        QSort(L, pivot + 1, high);
    }

}

int Partition(SqList *L, int low, int high)
{
    int pivotkey;
    pivotkey = L->r[low];
    while (low < high)
    {
        while (low < high && L->r[high] >= pivotkey)
        {
            high--;
        }
        swap(L, low, high);
        while (low < high && L->r[low] <= pivotkey)
        {
            low++;
        }
        swap(L, low, high);
    }
    return low;

}

5、总结

稳定性:排序算法的稳定性:若待排序的序列中,存在多个具有相同关键字的记录,经过排序, 这些记录的相对次序和排序之前相同,则称该算法是稳定的;

若排序后,记录的相对次序和排序前不同,则该算法是不稳定的。

稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序

不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序

当待排序序列顺序或基本有序时,直接插入排序和冒泡排序将大大减少比较次数和移动记录的次数,时间复杂度可降至O(n);

而快速排序则相反,当待排序序列基本有序时,将蜕化为冒泡排序,时间复杂度提高为O(n2);

待排序序列是否有序,对简单选择排序、堆排序、归并排序和基数排序的时间复杂度影响不大。

下面是转于别人的程序

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100

//排序用的顺序表结构
typedef struct{
    int r[MAXSIZE + 1];//用于存储要排序数组,r[0]用做哨兵或临时变量
    int length;
}SqList;

//交换两个值
void swap(SqList *L, int i, int j){
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;
}

//冒泡排序
void BubbleSort(SqList *L){
    int i, j, k = 0, l = 0;
    for (i = 1; i<L->length; i++){//外层循环,确定所有数都与其它数比较
        //k++;
        for (j = i + 1; j <= L->length; j++){//内层循环,用一个数跟其它数比较大小
            k++;
            if (L->r[i] > L->r[j]){
                swap(L, i, j);
                l = l + 3;
            }
        }
    }
    printf("冒泡排序中关键字的比较次数为%d:", k);
    printf("\n冒泡排序中关键字的移动次数为%d:", l);
    printf("\n");
}

//直接排序
void InsertSort(SqList *L) {
    int i, j, k = 0, l = 0;
    for (i = 2; i <= L->length; i++){
        k++;
        if (L->r[i] < L->r[i - 1]){
            L->r[0] = L->r[i];//设置哨兵
            l++;
            for (j = i - 1; L->r[j] > L->r[0]; j--){
                L->r[j + 1] = L->r[j];//记录后移
                l++;
                k++;
            }
            k++;//这一步容易忽略,跳出循环的时候,是比较了一次,不符合条件才跳出的
            L->r[j + 1] = L->r[0];//插入到正确位置
            l++;
        }
    }
    printf("直接排序中关键字的比较次数为%d:", k);
    printf("\n直接排序中关键字的移动次数为%d:", l);
    printf("\n");
}

//简单选择排序
void SelectSort(SqList *L){
    int i, j, min;
    int k = 0, l = 0;
    for (i = 1; i<L->length; i++){
        //k++;
        min = i;
        for (j = i + 1; j <= L->length; j++){
            k++;
            if (L->r[min] > L->r[j]){
                min = j;
            }
        }
        if (i != min){//判断 i!min,则证明有数据比 r[min]还要小,则需交换
            swap(L, i, min);
            l = l + 3;
        }
    }
    printf("简单排序中关键字的比较次数为:%d", k);
    printf("\n简单排序中关键字的移动次数为:%d", l);
    printf("\n");
}

//希尔排序
void ShellSort(SqList *L) {
    int i, j;
    int k = 0, l = 0;
    int increment = L->length;
    do{
        increment = increment / 5 + 1;//增量序列
        for (i = increment + 1; i <= L->length; i++){
            k++;
            if (L->r[i] < L->r[i - increment]){// 需要将L->r[i]插入有序增量子表
                L->r[0] = L->r[i];
                l++;
                for (j = i - increment; L->r[0]<L->r[j] && j>0; j = j - increment){
                    k++;
                    L->r[j + increment] = L->r[j];
                    l++;
                }
                k++;//这一步容易忽略,跳出循环的时候,是比较了一次,不符合条件才跳出的
                L->r[j + increment] = L->r[0];
                l++;
            }
        }
    } while (increment > 1);
    printf("希尔排序中关键字的比较次数为:%d", k);
    printf("\n希尔排序中关键字的移动次数为:%d", l);
    printf("\n");
}

//已知L->r[s..m]中记录的关键字除L->r[s]之外均满足堆的定义
//本函数调整L->r[s]的关键字,使L->r[s..m]成为一个大顶堆
void HeapAdjust(SqList *L, int s, int m, int &a, int &b){
    int temp, j;
    temp = L->r[s];
    b++;
    for (j = 2 * s; j <= m; j = j * 2){
        a++;
        if (L->r[j] < L->r[j + 1] && j<m)
            ++j;//j为关键字中较大的记录的下标
        a++;
        if (temp >= L->r[j])
            break;
        L->r[s] = L->r[j];
        b++;
        s = j;
    }
    L->r[s] = temp;
    b++;
}
//堆排序
void HeapSort(SqList *L) {
    int i;
    int k = 0, l = 0;
    for (i = L->length / 2; i>0; i--){//把L中的r构建成一个大顶堆
        HeapAdjust(L, i, L->length, k, l);
    }
    for (i = L->length; i>1; i--){
        swap(L, 1, i);//将堆顶记录和当前未经排序子序列的最后一个记录交换
        l = l + 3;
        HeapAdjust(L, 1, i - 1, k, l);//将L->r[1...i-1]重新调整为大顶堆
    }
    printf("堆排序中关键字的比较次数为:%d", k);
    printf("\n堆排序中关键字的移动次数为:%d", l);
    printf("\n");
}

//交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置
//此时在它之前(后)的记录均不大(小)于它
int Partition(SqList *L, int low, int high, int &k, int &l){
    int pivotkey;
    pivotkey = L->r[low];
    while (low<high){
        while (L->r[high] >= pivotkey && low<high){
            k++;
            high--;
        }
        k++;//这一步容易忽略,跳出循环的时候,是比较了一次,不符合条件才跳出的
        swap(L, low, high);
        l = l + 3;
        while (L->r[low] <= pivotkey && low<high){
            k++;
            low++;
        }
        k++;//这一步容易忽略,跳出循环的时候,是比较了一次,不符合条件才跳出的
        swap(L, low, high);
        l = l + 3;
    }
    return low;
}
//对顺序表L中的子序列L->r[low..high]作快速排序
void QSort(SqList *L, int low, int high, int &k, int &l){
    int pivot;//枢轴
    if (low<high){
        pivot = Partition(L, low, high, k, l);//将L->r[low..high]一分为二,算出枢轴值
        QSort(L, low, pivot - 1, k, l);//对低子表递归排序
        QSort(L, pivot + 1, high, k, l);//对高子表递归排序
    }
}

//快速排序
void QuickSort(SqList *L) {
    int k = 0, l = 0;
    QSort(L, 1, L->length, k, l);
    printf("快速排序中关键字的比较次数为:%d", k);
    printf("\n快速排序中关键字的移动次数为:%d", l);
    printf("\n");
}


int main(){
    int x, y;
    SqList L, L1, L2, L3, L4, L5;
    L.length = 100;

    for (int i = 0; i<5; i++){
        printf("第%d次待排序列为:\n", i + 1);
        for (x = 1; x<101; x++) {
            y = rand() % 100;
            L.r[x] = y;
            printf("%3d", y);
        }
        L1 = L2 = L3 = L4 = L5 = L;
        //fflush(stdin);
        printf("\n排序后的结果\n");
        BubbleSort(&L);
        printf("直接排序后的结果\n");
        InsertSort(&L1);
        printf("简单排序后的结果\n");
        SelectSort(&L2);
        printf("希尔排序后的结果\n");
        ShellSort(&L3);
        printf("堆排序后的结果\n");
        HeapSort(&L4);
        printf("快速排序后的结果\n");
        QuickSort(&L5);
        for (x = 1; x<101; x++) {
            printf("%3d", L.r[x]);
        }
        printf("\n");
    }
    while (1){//设置一个死循环,为了不让程序结束而关闭窗口

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jiaoyangwm/article/details/81428062