【数据结构C语言】排序

/*
第十章 内排序 上机实验
实验目的:熟悉掌握插入排序、交换排序和选择排序的思想和方法实现。
实验要求
设有一组记录{38,'b'},{65,'c'},{49,'a'},{97,'d'},{76,'e'},{13,'f'},{27,'g'},{49,'h'},其中每个记录第一个域的数字表示关键字,第二个域的字母表示记录信息。请按照关键字从小到大对记录进行排序,具体要求如下:
(1)实现直接插入排序,完成函数InsertSort,并输出每一次插入完成后顺序表中的记录,可以使用工程中的print函数进行输出;
(2)实现折半插入排序,完成函数BInsertSort,输出最后的排序结果;
(3)实现希尔排序,增量序列为dt={5,3,1},完成函数ShellInsert,ShellSort,并输出每一趟希尔插入排序之后的结果;
(4)实现快速排序,完成函数Partition,QSort和QuickSort,输出每一趟Partition之后的记录结果;
(5)实现选择排序,输出输出每一趟记录和最后的排序结果;
(6)比较不同算法中关键字相同的两个记录a与h在排序后的相对位置变化。
*/




#include<stdio.h>
#define MAXSIZE 20
typedef int KeyType;
typedef struct
{
    KeyType key;
    char name;
}RedType;




typedef struct
{
    RedType r[MAXSIZE+1];//r[0]闲置或用作哨兵
    int length;
}SqList;




//补.创建顺序表
void CreateList(SqList *L,RedType a[],int n)
{
    int i;
    for(i=1;i<=n;i++)
        (*L).r[i]=a[i-1];//直接把结构体类型数据赋给顺序表
    (*L).length=n;
}




//补.遍历
void PrintList(SqList L)
{
    int i;
    for(i=1;i<=L.length;i++)
    printf("{%d,'%c'}",L.r[i].key,L.r[i].name);
}




//算法8.1直接插入排序
void InsertSort(SqList *L)
{
    int i,j;
    for(i=2;i<=(*L).length;i++)//从第二个开始,把每一个元素插入到已排好的序列,直到最后一个
    if((*L).r[i].key<(*L).r[i-1].key)//如果下一个比上一个小,则执行语句。若下一个大于或等于上一个,则直接进入下一轮循环,不需插入
    {
        (*L).r[0]=(*L).r[i];//r[0]为哨兵
        (*L).r[i]=(*L).r[i-1];//把r[r-1]移动到第r个位置
        for(j=i-2;(*L).r[0].key<(*L).r[j].key;--j)//从后向前寻找插入的位置
            (*L).r[j+1]=(*L).r[j];//记录逐个后移,直到找到插入的位置
        (*L).r[j+1]=(*L).r[0];//将r[i]插入到正确位置
    }
}
//直接插入排序,按步骤输出每次排序的结果
void InsertSort_steps(SqList *L)
{
    int i,j;
    for(i=2;i<=(*L).length;i++)//从第二个开始,把每一个元素插入到已排好的序列,直到最后一个
    {
        if((*L).r[i].key<(*L).r[i-1].key)//如果下一个比上一个小,则执行语句。若下一个大于或等于上一个,则直接进入下一轮循环
        {
            (*L).r[0]=(*L).r[i];//r[0]为哨兵
            (*L).r[i]=(*L).r[i-1];//把r[r-1]移动到第r个位置
            for(j=i-2;(*L).r[0].key<(*L).r[j].key;--j)//从后向前寻找插入的位置
                (*L).r[j+1]=(*L).r[j];//记录逐个后移,直到找到插入的位置
            (*L).r[j+1]=(*L).r[0];//将r[i]插入到正确位置
        }
        printf("第%d次插入:",i-1);
        PrintList((*L));
        printf("\n");
    }




}




//算法8.2折半插入排序
//折半插入排序也是插入排序,它与直接插入排序不同的是,寻找插入位置的方法不同
void BInsertSort(SqList *L)
{
    int i,j,low,high,m;
    for(i=2;i<=(*L).length;++i)//从第二个开始,把每一个元素插入到已排好的序列,直到最后一个
    {
        (*L).r[0]=(*L).r[i];
        low=1;high=i-1;
        while(low<=high)
        {
            m=(low+high)/2;
            if((*L).r[0].key<(*L).r[m].key) high=m-1;
            else low=m+1;
        }
        for(j=i-1;j>=high+1;--j) (*L).r[j+1]=(*L).r[j];//记录逐个后移
        (*L).r[high+1]=(*L).r[0];//将r[i]插入到正确位置
    }
}
//折半插入排序,按步骤输出每次排序的结果
void BInsertSort_steps(SqList *L)
{
    //虽然输出结果与直接插入排序结果形同,但是查找正确位置的时间变短了
    int i,j,low,high,m;
    for(i=2;i<=(*L).length;++i)//从第二个开始,把每一个元素插入到已排好的序列,直到最后一个
    {
        (*L).r[0]=(*L).r[i];
        low=1;high=i-1;
        while(low<=high)
        {
            m=(low+high)/2;
            if((*L).r[0].key<(*L).r[m].key) high=m-1;
            else low=m+1;
        }
        for(j=i-1;j>=high+1;--j) (*L).r[j+1]=(*L).r[j];//记录逐个后移
        (*L).r[high+1]=(*L).r[0];//将r[i]插入到正确位置
        printf("第%d次插入:",i-1);
        PrintList((*L));
        printf("\n");
    }
}




//算法8.3希尔排序
void ShellInsert(SqList *L,int dk)
{
    int i,j;
    for(i=dk+1;i<(*L).length;i++)
        if((*L).r[i].key<(*L).r[i-dk].key)
        {
            (*L).r[0]=(*L).r[i];
            for(j=i-dk;j>0&&(*L).r[0].key<(*L).r[j].key;j-=dk)
               (*L).r[j+dk]=(*L).r[j];
            (*L).r[j+dk]=(*L).r[0];
        }
}
void ShellSort(SqList *L,int dt[],int t)
{
    int k;
    for(k=0;k<t;++k)
        ShellInsert(&(*L),dt[k]);
}
//希尔插入排序,按步骤输出每次排序的结果
void ShellSort_steps(SqList *L,int dt[],int t)
{
    int k;
    for(k=0;k<t;++k)
    {
        ShellInsert(&(*L),dt[k]);
        printf("第%d趟排序:",k+1);
        PrintList((*L));
        printf("\n");
    }
}




//算法8.5快速牌序
//设枢纽关键字,把小于关键字的放在左边,大于关键字的放在右边,递归调用。
int Partition(SqList *L,int low,int high)
{
    //返回枢纽位置,并把小于关键字的放在枢纽左边,大于关键字的放在枢纽右边
    KeyType pivotkey;
    (*L).r[0]=(*L).r[low];//做枢纽记录
    pivotkey=(*L).r[low].key;//枢纽的关键字保存在pivotkey中
    while(low<high)
    {
        while(low<high&&(*L).r[high].key>=pivotkey) --high;
        (*L).r[low]=(*L).r[high];
        while(low<high&&(*L).r[low].key<=pivotkey) ++low;
        (*L).r[high]=(*L).r[low];
    }
    (*L).r[low]=(*L).r[0];
    return low;
}




void QSort(SqList *L,int low,int high)
{
    int pivotloc;
    if(low<high)
    {
        pivotloc=Partition(&(*L),low,high);
        QSort(&(*L),low,pivotloc-1);
        QSort(&(*L),pivotloc+1,high);
    }
}




void QuickSort(SqList *L)
{
    QSort(&(*L),1,(*L).length);
}




//快速排序,按步骤输出每次排序的结果
int count=1;
void QSort_steps(SqList *L,int low,int high)
{
    int pivotloc;
    if(low<high)
    {
        pivotloc=Partition(&(*L),low,high);
        printf("\n第%d次排序为:",count++);
        PrintList(*L);
        QSort_steps(&(*L),low,pivotloc-1);
        QSort_steps(&(*L),pivotloc+1,high);
    }
}
void QuickSort_steps(SqList *L)
{
    QSort_steps(&(*L),1,(*L).length);
}




//算法8.6简单选择排序
void SelectSort(SqList *L)
{
    int i,j,k;
    RedType t;
    for(i=1;i<(*L).length;++i)
    {
        k=i;
        for(j=i+1;j<=(*L).length;++j)
            if((*L).r[j].key<(*L).r[k].key) k=j;
        if(k!=i)
        {
            t=(*L).r[i];(*L).r[i]=(*L).r[k];(*L).r[k]=t;
        }
    }
}


//简单选择排序,按步骤输出每次排序结果
void SelectSort_steps(SqList *L)
{
    int i,j,k;
    RedType t;
    for(i=1;i<(*L).length;++i)
    {
        k=i;
        for(j=i+1;j<=(*L).length;++j)
            if((*L).r[j].key<(*L).r[k].key) k=j;
        if(k!=i)
        {
            t=(*L).r[i];(*L).r[i]=(*L).r[k];(*L).r[k]=t;
        }
        printf("\n第%d次排序为:",i);
        PrintList(*L);
    }
}


int main()
{
    SqList L;
    RedType a[8]={{49,'a'},{38,'b'},{65,'c'},{97,'d'},{76,'e'},{13,'f'},{27,'g'},{49,'h'}};




//************************************************
    CreateList(&L,a,8);
    InsertSort(&L);
    printf("直接插入排序后,最终结果是:");
    PrintList(L);
    printf("\n");




    CreateList(&L,a,8);
    printf("直接插入排序的过程:\n");
    InsertSort_steps(&L);
    printf("\n\n");




//************************************************




    CreateList(&L,a,8);
    BInsertSort(&L);
    printf("折半插入排序后,最终结果是:");
    PrintList(L);
    printf("\n");




    CreateList(&L,a,8);
    printf("折半插入排序的过程:\n");
    BInsertSort_steps(&L);
    printf("\n\n");




//************************************************




    CreateList(&L,a,8);
    int dt[3]={5,3,1};
    ShellSort(&L,dt,3);
    printf("希尔排序后,最终结果是:");
    PrintList(L);
    printf("\n");




    CreateList(&L,a,8);
    printf("希尔排序的过程(增量为%d,%d,%d):\n",dt[0],dt[1],dt[2]);
    ShellSort_steps(&L,dt,3);
    printf("\n\n");








//************************************************




    CreateList(&L,a,8);
    QuickSort(&L);
    printf("快速排序后,最终结果是:");
    PrintList(L);




    CreateList(&L,a,8);
    printf("\n快速排序的过程:");
    QuickSort_steps(&L);
    printf("\n\n");








//************************************************




    CreateList(&L,a,8);
    SelectSort(&L);
    printf("\n简单选择排序后,最终结果是:");
    PrintList(L);




    CreateList(&L,a,8);
    printf("\n简单选择排序的过程:");
    SelectSort_steps(&L);
    printf("\n\n");






//************************************************




    return 0;


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值