第一题
这一题的想法是让大家熟悉并掌握结构体的定义和使用,这块就不多赘述,结构体的定义可以帮助我们将想要的一些信息整合起来,防止进行排序或者其他变量的赋值和交换的时候出现问题。
简单谈一下稳定性这个概念,稳定性就是数组中值相等的两个元素,在排序完成之后,他们之间的相对顺序不发生改变,常见排序算法的稳定性可以参考这个地方。常见排序算法总结归纳
#include<iostream>
#include<cstdlib>
using namespace std;
struct candidate{
string name ;
int count ;
void init()
{
cin >> name;
count = 0;
}
void swap(candidate &other) {
name.swap(other.name);
int tmp = count;
count = other.count;
other.count = tmp;
}
};
int main()
{
int n,m;
cin >> n >>m;
candidate record[n]={};
for(int i=0;i<n;i++)
{
record[i].init();
}
string cur;
for(int i = 0; i < m;i++)
{
cin >>cur;
for(int j =0 ;j < n;j++)
{
if(record[j].name == cur)//string类可以这么写,char数字要自己用strcpy
record[j].count++;
}
}
for(int i=0;i<n;i++)
{
for(int j = n - 1 ; j > i; j--)
{
if(record[j].count >record[j - 1].count)
record[j].swap(record[j -1]);
}
}
for(int i = 0;i<n;i++)
{
cout <<record[i].name<<" "<<record[i].count<<" ";
}
return 0;
}
第二题
这个结构体存在的问题比较集中的地方在于最后的地址那,有些同学会觉得题目给的例子中有5个字符串就使用cin>>string直接读取5个字符串,但其实题目中没有说明地址这块会分为5个字符串,而且测试集也可以看到字符串的数量是不稳定的,所有这块还是使用cin.getline比较好。要依据不同的输入格式及时调整
#include <iostream>
using namespace std;
struct AddressBook
{
struct BirthDay
{
int year, month, day;
};
char name[21];
BirthDay birth;
long long phonenum;
char address[51];
void init() {
cin >> name >> birth.year >> birth.month >> birth.day >> phonenum;
cin >> ws; cin.getline(address, 51, '\n');
}
void disp() {
printf("%s %d %d %d %lld %s\n", name, birth.year, birth.month, birth.day, phonenum, address);
}
int birthday() {
// 辅助 sort
return birth.year * 10000 + birth.month * 100 + birth.day;
}
};
void bubbleSort(AddressBook* A, int n) {
// sort by birthday
for (int i=n-1; i>=0; --i) {
bool exist_swap = false;
for (int j=0; j<i; ++j) {
if (A[j].birthday() < A[j+1].birthday()) swap(A[j], A[j+1]), exist_swap = true;
}
if (! exist_swap) break;
}
}
int main(int argc, char const *argv[])
{
int n;
cin >> n;
AddressBook books[10];
for (int i=0; i<n; ++i) {
books[i].init();
}
bubbleSort(books, n);
for (int i=0; i<n; ++i) {
books[i].disp();
}
return 0;
}
第三题
这个题目的错误还是比较明显的,首先是错误的输出这个不多说,其次是while循环中这一部分
下节课老师会讲到这一部分的内容,这是链表中很经典的一种建表方法,被称为头插法,也就是将新生成的结点插入链表的表头,具体的可以看老师ppt上有关该部分的动画加深理解
第二个地方就是输出的for循环那,明显可以看出按照给的条件来看最后会少输出一个结点,所以要修改一下判定条件,这些地方修改完毕之后就可以通过了
#include <iostream>
using namespace std;
struct List
{
int num;
List *next;
};
int main()
{
List *head, *p, *q;
int num;
head = NULL;
// cout << "请输入若干个正整数(-1结束)\n";
cin >> num;
while(num != -1)
{
p = new List;
p->num = num;
p->next = head;
head = p;
cin >> num;
}
// cout << "按照输入顺序逆序输出\n";
for(p = head; p != NULL; p = p->next)
{
cout << p->num << " ";
};
cout << endl;
for(p = head; p != NULL; p = q)
{
q = p->next;
delete p;
}
return 0;
}
第四题
这个题目主要理解翻转链表要干啥,基本思路就是将下一个结点的next指针指向自己同时又能保证链表的递归遍历,这样就可以比较轻松得出下面的算法:
- 首先定义pre,cur ,next三个指针(注意与结点内的next进行区分),cur初值为head。
- 遍历过程中首先要判断cur是否为空,不为空则让next暂存下一个结点的地址(也就是cur->next),cur的next指针指回到pre,这样就完成了一次当前结点的指针的翻转,随后更新pre,cur的值即可
对第一个结点的操作可以看下面几张图(注意next只起到一个暂时存放地址的作业,所以一次操作前next值为啥都无所谓)
ListNode* reverseList(ListNode* head) {
/********* Begin *************/
ListNode* prev = NULL, *curr = head, *next;
while (curr) {
next = curr->next; curr->next = prev;
prev = curr; curr = next;
}
return prev;
/********* End *************/
}