背景
学生成绩统计:
给出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);
}
}