第9章 排序算法

背景

学生成绩统计:
给出n个学生的考试成绩表,每条信息由姓名和分数组成,试设计一个算法。

数据结构

根据题意不能直接把分数进行数字比较,而是要建立student的数据结构

typedef struct
{
    char name[8];
    int score;
} student;

算法

以下代码中的 n 为主函数输入的学生信息个数。
所有算法最终都是以降序排序。

直接插入排序法

类似打扑克时整理手牌。开始时,拿到手的第1张牌无须整理,此后每次从桌上的牌(无序区)中拿到最上面的1张 牌,并插入原来已在手的牌(有序区)中正确的位置上。为了找到这个正确的位置,须自左向右(或自右向左)将新拿到的牌与原来已在手的牌逐一比较。

void InsertSort(student stu[],int n)
{
    int i,j;
    student temp;
    for ( i = 1; i < n; i++)
    {
        temp=stu[i];
        j=i-1;
        while (temp.score>stu[j].score&&j>-1)
        {
            stu[j+1]=stu[j];
            j--;
        }
        stu[j+1]=temp;
    } 
}

直接选择排序法

void SelectSort(student stu[], int n) 
{
    int  i, j, max;
    student temp;
    for (i = 0; i < n; i++)
    {
        max = i;
        for (j = i + 1; j < n; j++)
            if (stu[j].score > stu[max].score)
                max = j;
        if (max != i)
        {
            temp = stu[max];
            stu[max] = stu[i];
            stu[i] = temp;
        }
    }
}

冒泡排序

void BubbleSort(student stu[],int n)
{
    int i,j,flag;
    student temp;
    for ( i = 0; i < n; i++)
    {
    	flag=0;
       for ( j = 0; j < n-i-1; j++)
           if (stu[j].score<stu[j+1].score)
           {
               temp=stu[j];
               stu[j]=stu[j+1];
               stu[j+1]=temp;
               flag=1;
           }
       if(!flag) break;
    }
}

希尔排序

直接插入排序的改进,实际上是一种分组插入方法。

void ShellPass(student stu[],int d,int n)
{
    int i,j;
    student temp;
    for ( i = d; i < n; i++)
    {
        if(stu[i].score>stu[i-d].score)
        {
            temp=stu[i];
            j=i-d;
            do
            {
                stu[j+d]=stu[j];
                j=j-d;
            } while (j>=0&&temp.score>stu[j].score);
            stu[j+d]=temp;            
        }
    }
}
void ShellSort(student stu[],int n)//希尔排序 
{
    int increment =n;
    do
    {
        increment=increment/2;
        ShellPass(stu,increment,n);
    } while (increment>1);
}

快速排序

主要分为三步:
1.分解:找出基准记录所在的位置 pivotpos,划分左右区间
2.求解:通过递归调用快速排序对左、右子区间stu[ low到pivotpos- 1]和stu[pivotpos+ 1到high]快速排序
3.组合:通过递归调用快速排序对左、右子区间 stu[ low 到 pivotpos- 1] 和 stu[pivotpos+ 1 到 high]快速排序

int Partition(student stu[],int i,int j)//划分算法 
{
    student pivot=stu[i];
    while (i<j)
    {
        while (i<j&&stu[j].score<=pivot.score)
            j--;
        if(i<j)
            stu[i++]=stu[j];
        while (i<j&&stu[i].score>=pivot.score)
        {
            i++;
        }
        if(i<j)
            stu[j--]=stu[i];
    }
    stu[i]=pivot;
    return i;
    
}
void QuickSort(student stu[],int low,int high)//快速排序 
{
    int pivotpos;
    if(low<high)
    {
        pivotpos=Partition(stu,low,high);
        QuickSort(stu,low,pivotpos-1);
        QuickSort(stu,pivotpos+1,high);
    }
}

堆排序

注:小根堆排序
1.先初始化建立小根堆,此堆为无序区
2.将score最大的记录stu[0]和无序区的最后一个记录stu[n-1]交换,由此得到新的有序区stu[n-1]
3.将当前无序区stu[1 到 n-2]重新调整为堆,以此类推,一直到无序区只有1个元素为止

void Heapify(student stu[],int k, int m)
{
    student temp=stu[k];
    int x=stu[k].score;
    int i=k;
    int j=2*i;
    while (j<=m)
    {
        if(j<m&&stu[j].score>stu[j+1].score)
            j++;
        if(x>stu[j].score)
        {
            stu[i]=stu[j];
            i=j;
            j=2*i;
        }
        else
            break;        
    }
    stu[i]=temp;
}
void BuildHeap(student stu[],int n)
{
    int i;
    for ( i = n/2; i >=0; i--)
    {
        Heapify(stu,i,n);
    }
    
}
void  HeapSort(student stu[],int n)//小根堆排序 
{
    int i;
    student temp;
    BuildHeap(stu,n);
    for ( i = n; i >0; i--)
    {
        temp=stu[0];
        stu[0]=stu[i];
        stu[i]=temp;
        Heapify(stu,0,i-1);
    }
}

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值