第六周作业
(学生信息处理问题)有这样一种学生结构体类型,其数据成员有包括学号,姓名和3门课程的成绩。实现下列要求:
(a). 从键盘输入5个学生的信息,将这些同学的信息采用结构体数组的方式存储起来。
(b). 将学生信息按照学号重新排序,并且输出到控制台上。
(c). 输出每门课程最高分的学生信息。
(d). 输出每门课程的平均分。
(e). 按照总分输出学生排名。
c
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct student_s {
int id;
char name[25];
float score1;
float score2;
float score3;
} student_t;
void info_input(student_t * stu_arr,int len); //输入学生信息
void sort_by_id(student_t *stu_arr,int len); //按照学号排序
void print_arr(student_t *stu_arr,int len); // 打印数组
void find_max_score1(student_t *stu_arr, int len); //找score1最高分
void find_max_score2(student_t *stu_arr, int len); //找score2最高分
void find_max_score3(student_t *stu_arr, int len); //找score3最高分
void print_average_score(student_t *stu_arr, int len); //打印平均分
void sort_by_score(student_t *stu_arr, int len); //按照总分排序
int main(){
student_t stu_arr[5];
info_input(stu_arr,5);
printf("-----------------------\n");
sort_by_id(stu_arr,5);
printf("-----------------------\n");
find_max_score1(stu_arr,5);
find_max_score2(stu_arr,5);
find_max_score3(stu_arr,5);
printf("-----------------------\n");
print_average_score(stu_arr,5);
printf("-----------------------\n");
sort_by_score(stu_arr,5);
return 0;
}
void info_input(student_t * stu_arr,int len){
for(int i = 0; i < len; ++i){
scanf("%d%s%f%f%f",
&stu_arr[i].id,stu_arr[i].name, //由于name字段是字符数组,所以可以不用加&符号
&stu_arr[i].score1,&stu_arr[i].score2,&stu_arr[i].score3);
}
}
void sort_by_id(student_t *stu_arr,int len){
// 这里使用了冒泡排序
for(int i = len; i >= 1; --i){ // 依次遍历前len、len-1、... 3、2个元素
for(int j = 0; j < i-1; ++j){ // 下标从0遍历到i-1,试图找到前i个数的最大值
if(stu_arr[j].id > stu_arr[j+1].id){ //如果左边的元素比右边的大,则发生交换
student_t temp = stu_arr[j];
stu_arr[j] = stu_arr[j+1];
stu_arr[j+1] = temp;
}
}
}
print_arr(stu_arr,5);
}
void print_arr(student_t *stu_arr,int len){
for(int i = 0; i < len; ++i){
printf("%d %s %g %g %g\n",
stu_arr[i].id, stu_arr[i].name,
stu_arr[i].score1, stu_arr[i].score2, stu_arr[i].score3);
}
}
void find_max_score1(student_t *stu_arr, int len){
int max_i = 0;
int max_score1 = stu_arr[0].score1;
for(int i = 1; i < len; ++i){
if(stu_arr[i].score1 > max_score1){
max_i = i;
max_score1 = stu_arr[i].score1;
}
}
printf("max score1: %d %s %g %g %g\n",
stu_arr[max_i].id, stu_arr[max_i].name,
stu_arr[max_i].score1, stu_arr[max_i].score2, stu_arr[max_i].score3);
}
void find_max_score2(student_t *stu_arr, int len){
int max_i = 0;
int max_score2 = stu_arr[0].score2;
for(int i = 1; i < len; ++i){
if(stu_arr[i].score2 > max_score2){
max_i = i;
max_score2 = stu_arr[i].score2;
}
}
printf("max score2: %d %s %g %g %g\n",
stu_arr[max_i].id, stu_arr[max_i].name,
stu_arr[max_i].score1, stu_arr[max_i].score2, stu_arr[max_i].score3);
}
void find_max_score3(student_t *stu_arr, int len){
int max_i = 0;
int max_score3 = stu_arr[0].score3;
for(int i = 1; i < len; ++i){
if(stu_arr[i].score3 > max_score3){
max_i = i;
max_score3 = stu_arr[i].score3;
}
}
printf("max score2: %d %s %g %g %g\n",
stu_arr[max_i].id, stu_arr[max_i].name,
stu_arr[max_i].score1, stu_arr[max_i].score2, stu_arr[max_i].score3);
}
void print_average_score(student_t *stu_arr, int len){
float sum1 = 0;
float sum2 = 0;
float sum3 = 0;
for(int i = 0; i < len; ++i){
sum1 += stu_arr[i].score1;
sum2 += stu_arr[i].score2;
sum3 += stu_arr[i].score3;
}
printf("avg score1 = %g, avg score2 = %g, avg score3 = %g\n", sum1/len, sum2/len, sum3/len);
}
void sort_by_score(student_t *stu_arr, int len){
for(int i = len; i >= 1; --i){
for(int j = 0; j < i-1; ++j){
if(stu_arr[j].score1 + stu_arr[j].score2 + stu_arr[j].score3 >
stu_arr[j+1].score1 + stu_arr[j+1].score2 + stu_arr[j+1].score3){
student_t temp = stu_arr[j];
stu_arr[j] = stu_arr[j+1];
stu_arr[j+1] = temp;
}
}
}
print_arr(stu_arr,5);
}下面是链表结点类型的声明:
c
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;- 假设存在两个链表,链表的各个结点数据域都是有序的。要求合并这两个链表,并且合并之后也是有序的。本题中不能重新申请堆空间。
c
void merge_list(link_list_t *l1, link_list_t *l2, link_list_t * result){
node_t *pcur1 = l1->phead;
node_t *pcur2 = l2->phead;
while(pcur1 != NULL && pcur2 != NULL){
//分别遍历两个链表,将较小的结点以尾插法的方式插入结果当中
if(pcur1->data < pcur2->data){
if(result->phead == NULL){
result->phead = pcur1;
result->ptail = pcur1;
}
else{
result->ptail->next = pcur1;
result->ptail = pcur1;
}
pcur1 = pcur1->next;
}
else {
if(result->phead == NULL){
result->phead = pcur2;
result->ptail = pcur2;
}
else{
result->ptail->next = pcur2;
result->ptail = pcur2;
}
pcur2 = pcur2->next;
}
}
//如果是第一个链表有剩余结点
if(pcur1 != NULL){
result->ptail->next = pcur1;
result->ptail = l1->ptail;
}
//如果是第二个链表有剩余结点
if(pcur2 != NULL){
result->ptail->next = pcur2;
result->ptail = l2->ptail;
}
}- 假设链表的长度大于4,要求找到倒数第4个结点。
c
void find_last_4th(link_list_t *l){
node_t * ppre = l->phead; //慢指针指向第一个结点
node_t * pcur; //快指针
if(ppre && ppre->next && ppre->next->next && ppre->next->next->next){
pcur = ppre->next->next->next;
//一开始快指针在第4个位置,慢指针在第一个位置
}
else{
printf("error, length less than 4!\n");
return;
}
while(pcur != l->ptail){//快慢指针同速度后移,直到快指针到达倒数第一个结点
pcur = pcur->next;
ppre = ppre->next;
}
printf("the 4th last = %d\n", ppre->data);
}c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//先设计链表的某一个结点
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;
void tail_insert(link_list_t* plist, int data) {
node_t* pnew_node = (node_t*)malloc(sizeof(node_t));
pnew_node->next = NULL;
pnew_node->data = data;
if (plist->phead == NULL) {
plist->phead = pnew_node;
plist->ptail = pnew_node;
}
else {
plist->ptail->next = pnew_node;
plist->ptail = pnew_node;
}
}
void print_list(link_list_t* plist) {
node_t* pcur = plist->phead;
while (pcur != NULL) {
printf("%d", pcur->data);
if (pcur->next != NULL) { // 不是最后一个结点
printf(" ");
}
pcur = pcur->next; // 每次需要将游标后移
}
printf("\n");
}
int main(){
int d;
link_list_t list = {NULL,NULL};
while(scanf("%d", &d), d > 0){ //按顺序插入就是做尾插法
tail_insert(&list,d);
}
print_list(&list);
return 0;
}c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//先设计链表的某一个结点
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;
void head_insert(link_list_t* plist, int data) {
node_t* pnew_node = (node_t *)malloc(sizeof(node_t));
pnew_node->next = NULL;
pnew_node->data = data;
if (plist->phead == NULL) {
plist->phead = pnew_node;
plist->ptail = pnew_node;
}
else {
pnew_node->next = plist->phead;
plist->phead = pnew_node;
}
}
void print_list(link_list_t* plist) {
node_t* pcur = plist->phead;
while (pcur != NULL) {
printf("%d", pcur->data);
if (pcur->next != NULL) { // 不是最后一个结点
printf(" ");
}
pcur = pcur->next; // 每次需要将游标后移
}
printf("\n");
}
int main(){
int d;
link_list_t list = {NULL,NULL};
while(scanf("%d", &d), d > 0){ //逆序输入就是做头插法
head_insert(&list,d);
}
print_list(&list);
return 0;
}c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;
void tail_insert(link_list_t* plist, int data) {
node_t* pnew_node = (node_t*)malloc(sizeof(node_t));
pnew_node->next = NULL; //新结点的指针域一开始总是NULL
pnew_node->data = data;
if (plist->phead == NULL) {
plist->phead = pnew_node;
plist->ptail = pnew_node;
}
else {
plist->ptail->next = pnew_node;
plist->ptail = pnew_node;
}
}
void find_bigger_x(link_list_t* plist, int x) {
node_t* pcur = plist->phead;
int flag = 0; // flag用来记录是否有比x大的元素
while (pcur != NULL) {
if(pcur->data > x){
flag = 1;
printf("%d ", pcur->data);
}
pcur = pcur->next;
}
if(flag == 0){
printf("no found");
}
printf("\n");
}
int main(){
int d, x;
link_list_t list = {NULL,NULL};
while(scanf("%d", &d), d > 0){
tail_insert(&list,d);
}
scanf("%d", &x);
find_bigger_x(&list,x);
return 0;
}c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;
void print_list(link_list_t* plist) {
node_t* pcur = plist->phead;
while (pcur != NULL) {
printf("%d", pcur->data);
if (pcur->next != NULL) { // 不是最后一个结点
printf(" ");
}
pcur = pcur->next; // 每次需要将游标后移
}
printf("\n");
}
void tail_insert(link_list_t* plist, int data) {
node_t* pnew_node = (node_t*)malloc(sizeof(node_t));
pnew_node->next = NULL; //新结点的指针域一开始总是NULL
pnew_node->data = data;
if (plist->phead == NULL) {
plist->phead = pnew_node;
plist->ptail = pnew_node;
}
else {
plist->ptail->next = pnew_node;
plist->ptail = pnew_node;
}
}
void list_delete(link_list_t* plist, int x) {
node_t *pcur = plist->phead; //用来遍历所有结点
node_t *ppre = NULL; //用来记录pcur结点的前驱,如果NULL说明pcur为第一个结点
while(pcur != NULL){
if(pcur->data > x){ // 这个情况需要删除结点
if(pcur == plist->phead){ // 根据是否需要修改phead和ptail来分类讨论
// 如果删除的是第一个结点,只用改phead的指向
node_t *old = pcur;
plist->phead = pcur->next; //将phead后移
pcur = pcur->next; //pcur也需要后移
free(old);
}
else if(pcur != plist->phead){
// 如果删除的不是第一个结点,则需要找到被删结点的前驱结点,修改其指针域
node_t *old = pcur;
ppre->next = pcur->next; //修改前驱结点的指针域,跳过pcur
if(pcur == plist->ptail){
plist->ptail = ppre;
}
pcur = pcur->next; //pcur后移,ppre不变位置
free(old);
}
}
else{
//如果不需要删除结点,则pcur和ppre都需要后移
ppre = pcur;
pcur = pcur->next;
}
}
}
int main() {
int d,x;
link_list_t list = {NULL, NULL};
while(scanf("%d", &d), d > 0){
tail_insert(&list,d);
}
scanf("%d", &x);
list_delete(&list,x);
print_list(&list);
return 0;
}c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;
void print_list(link_list_t* plist) {
node_t* pcur = plist->phead;
while (pcur != NULL) {
printf("%d", pcur->data);
if (pcur->next != NULL) { // 不是最后一个结点
printf(" ");
}
pcur = pcur->next; // 每次需要将游标后移
}
printf("\n");
}
void tail_insert(link_list_t* plist, int data) {
node_t* pnew_node = (node_t*)malloc(sizeof(node_t));
pnew_node->next = NULL; //新结点的指针域一开始总是NULL
pnew_node->data = data;
if (plist->phead == NULL) {
plist->phead = pnew_node;
plist->ptail = pnew_node;
}
else {
plist->ptail->next = pnew_node;
plist->ptail = pnew_node;
}
}
void insert_x(link_list_t *plist, int x, int k){
node_t *pcur = plist->phead;
for(int i = 1; i < x; ++i){
pcur = pcur->next;
}//循环结束之后,pcur指向链表中第x个结点(当x大于等于1时,不用考虑头插的可能性)
//准备好新结点
node_t* pnew_node = (node_t*)malloc(sizeof(node_t));
pnew_node->next = NULL;
pnew_node->data = k;
//将新结点插入pcur和pcur后继之间
pnew_node->next = pcur->next;
pcur->next = pnew_node;
if(pnew_node->next == NULL){ //假如插入的是最后一个结点
plist->ptail = pnew_node;
}
}
void delete_y(link_list_t *plist, int y){
node_t *pcur = plist->phead;
if(y == 1){ //删除第一个结点需要做头部删除
plist->phead = pcur->next;
if(pcur->next == NULL){
plist->ptail = NULL;
}
free(pcur);
}
else{
for(int i = 1; i < y-1; ++i){ //找到第y-1个结点
pcur = pcur->next;
}
node_t *old = pcur->next;
pcur->next = old->next;
if(pcur->next == NULL){
plist->ptail = pcur;
}
free(old);
}
}
int main() {
int n,d,x,y,k;
link_list_t list = {NULL,NULL};
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d", &d);
tail_insert(&list,d);
}
scanf("%d%d",&x,&y);
scanf("%d",&k);
insert_x(&list,x,k);
delete_y(&list,y);
print_list(&list);
return 0;
}c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node_s {
int data;
struct node_s* next;
} node_t;
typedef struct link_list_s {
node_t* phead;
node_t* ptail;
} link_list_t;
void tail_insert(link_list_t* plist, int data) {
node_t* pnew_node = (node_t*)malloc(sizeof(node_t));
pnew_node->next = NULL;
pnew_node->data = data;
if (plist->phead == NULL) {
plist->phead = pnew_node;
plist->ptail = pnew_node;
}
else {
plist->ptail->next = pnew_node;
plist->ptail = pnew_node;
}
}
void print_list(link_list_t* plist) {
node_t* pcur = plist->phead;
while (pcur != NULL) {
printf("%3d", pcur->data);
if (pcur->next != NULL) { // 不是最后一个结点
printf("-> ");
}
pcur = pcur->next; // 每次需要将游标后移
}
printf("\n");
}
int circle(link_list_t *plist, int m){
node_t *pcur = plist->phead;//pcur是当前位置 从头开始遍历,到ptail之后回到phead
node_t *ppre = plist->ptail;//ppre是pcur的前一个位置
int count = 1;
while(plist->phead != plist->ptail){ //当链表中有不止一个结点的时候持续循环
if(count != m){//pcur不用被删除
ppre = pcur;
// pcur后移
if(pcur == plist->ptail){ //如果当前是ptail,则下一个为phead
pcur = plist->phead;
}
else{
pcur = pcur->next;
}
++count;
}
else { //要删除pcur结点
if(pcur == plist->phead){ // 假如pcur为第一个结点 则ppre是最后一个结点
node_t *old = plist->phead;
pcur = pcur->next;
plist->phead = pcur;
free(old);
}
else{ //假如pcur不是第一个结点
node_t *old = pcur;
if(pcur == plist->ptail){
pcur = plist->phead; //下一个访问是phead
plist->ptail = ppre; //原来的ptail被删除
ppre->next = NULL;
}
else{
pcur = pcur->next;
ppre->next = pcur;
}
free(old);
}
count = 1;
}
}
return plist->phead->data;
}
int main(){
link_list_t list = {NULL,NULL};
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; ++i){
tail_insert(&list,i);
}
printf("%d",circle(&list,m));
}