前言
本篇博客是在博主参加王道408专业课前置课程-----C语言督学营的学习笔记,包含了从第一节课到最后一节课的所有OJ习题题解,文章中每一题都给出了详尽的代码,并在每一题的关键部位加上了注释,记录下来的目的是方便自己以后进行复习,也希望能够帮助到大家,经过测试所有代码都可以通过王道OJ网站给出的样例,如果还有什么疑问的话评论区留言吧!(tips:网站上的样例比较简单,可能刷刷小聪明也可以通过,但是我建议大家还是按照要求来最好,毕竟是要锻炼自己的能力,投机取巧也不好!如果是感觉非常没有必要的能省则省。)
总体来说C语言督学营不算难,讲的知识很贴切考研考的知识点,前期主要对C语言语法进行了讲解,中后期补充了一些有关408的专业课知识点:
- 初级阶段
- C语言基础语法
- 数据类型&数据的输入输出
- 运算符与表达式
- 选择循环
- 一维数组与字符串
- 指针
- 函数
- 结构体与C++引用
- 中级阶段
- 简要介绍了C语言数据结构
- 顺序表基础操作
- 单链表基础操作
- 栈与队列基础操作
- 二叉树层次建树&层序遍历前中后序遍历&求WPL
- 顺序&二分&二叉排序树(查找算法)
- 冒泡&选择&插入&归并&快速&堆(排序算法)
- 另加一些数据结构相关的考研大题
- 高级阶段
- C语言语法补充(大多是考研不考的语法,或者有更好的替代)
- 数据的机器级表示(计组里面的一些基本概念&IEEE754浮点数表示法)
- 汇编语言入门
- C语言文件
- 另加一些计算机组成原理相关的大题
文章目录
- 初级阶段
- 课时二
- 作业1
- 作业2
- 作业3
- 课时三
- 作业1
- 作业2
- 课时四
- 作业1
- 作业2
- 作业3
- 课时五
- 作业1
- 作业2
- 课时六
- 作业1
- 作业2
- 课时七
- 课时八
- 作业1
- 作业2
- 中级阶段
- 课时十
- 课时十一
- 课时十二
- 课时十三
- 课时十四
- 作业1
- 作业2
- 课时十五
- 课时十六
- 课时十七
- 作业1
- 作业2
- 高级阶段
- 课时十九
- 作业1
- 作业2
- 课时二十
- 课时二十一
初级阶段
课时二
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
printf("hello wangdao");
return 0;
}
注意点
注意输入输出格式即可!HelloWord!
作业2
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int a,b;
scanf("%d %d",&a,&b);
printf("%d",a+b);
return 0;
}
注意点
这个题目没有坑,就是体验一下C语言语法,没有涉及到大数加法!
作业3
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int a;
scanf("%d",&a);
printf("%c",a);
return 0;
}
注意点
旨在锻炼学生ASCII值与字符之间的转化!这点在考研时挺重要的!
课时三
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int i;
scanf("%d",&i);
if (i%4==0&&i%100!=0||i%400==0){
printf("yes");
}else{
printf("no");
}
return 0;
}
注意点
闰年应该是能被4整除不能被100整除或者能被400整除的年份!
作业2
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int i;
char j;
float k;
scanf("%d %c %f",&i,&j,&k);
printf("%.2f",i+j+k);
return 0;
}
注意点
考察格式化输出!
课时四
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int i,j;
scanf("%d",&i);
j=i;
int ans=0;
while (i!=0) {
ans = ans * 10 + i % 10;
i /= 10;
}
if(j==ans){
printf("yes");
}else{
printf("no");
}
return 0;
}
注意点
考察循环语法的使用。
作业2
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int i,ans=1;
scanf("%d",&i);
for (int k=1;k<=i;k++){
ans*=k;
}
printf("%d",ans);
return 0;
}
作业3
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int a=100,ans=0;
for(int i=1;i<=40;i++){
for(int j=1;j<=40;j++){
for(int k=1;k<=40;k++){
for(int s=1;s<=40;s++){
if(i+j+k+s==40&&10*i+5*j+2*k+s==100){
ans+=1;
}
}
}
}
}
printf("%d",ans);
return 0;
}
注意点
数据量不算大,直接暴力搜索即可!
课时五
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int a,ans=0;
scanf("%d",&a);
int arr[a];
for(int i=0;i<a;i++){
scanf("%d",&arr[i]);
if(arr[i]==2){
ans+=1;
}
}
printf("%d\n",ans);
return 0;
}
注意点
无
作业2
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include "string.h"
int main() {
int a,ans=0;
char str[1000];
char str1[1000];
char c;
int i=0;
while(scanf("%c",&c)){
if(c=='\n') {
break;
}else{
str[i]=c;
i+=1;
}
}
// printf("%s\n",str);
int temp=strlen(str);
for(int i=temp-1;i>=0;i--){
str1[temp-i-1]=str[i];
}
// printf("%s\n",str1);
if((ans=strcmp(str,str1))==0){
printf("0");
return 0;
}
ans>0?printf("1"):printf("-1");
return 0;
}
注意点
这里考察字符串相关函数的使用以及字符的ASCII值!
课时六
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
void change(int *a){
(*a)=*a/2;
}
int main() {
int a;
scanf("%d",&a);
change(&a);
printf("%d",a);
}
注意点
无
作业2
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
void change(int *a){
(*a)=*a/2;
}
int main() {
int a;
char* p;
scanf("%d",&a);
//解决方案1 直接使用fflush刷新输入缓冲区(这种方法在OJ上一般不管用)
//fflush(stdin);
//解决方案2 吞掉第一次输入遗留的换行符
char c;
scanf("%c",&c);
p=(char*)malloc(a);
gets(p);
puts(p);
}
注意点
这个题目看似很简单,其实是个坑,因为在读取整形数据的时候会自动忽略最后输入的回车,所以下一个读取字符串会直接读取\n,我们需要做的就是在读取字符串之前刷新缓冲区或者把回车符吃掉!
课时七
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int runs(n){
if(n==1||n==2){
return n;
}
return runs(n-2)+runs(n-1);
}
int main() {
int n;
scanf("%d",&n);
printf("%d", runs(n));
return 0;
}
注意点
这个题目对小白来说可能比较困难,解这种类型的题目有好多解法,可以使用递归,动态规划等!
课时八
作业1
题目描述
AC代码
#include <stdio.h>
int main() {
char a[1000]={'\0'};
gets(a);
puts(a);
return 0;
}
注意点
无
作业2
题目描述
AC代码
//
// Created by 123 on 2023/2/14.
//
#include <stdio.h>
#include <stdlib.h>
void myfgets(char *&p){
p=(char *)malloc(100);
fgets(p,100,stdin);
}
int main(){
char *p;
myfgets(p);
puts(p);
return 0;
}
注意点
在被调函数中申请的变量会随着函数的生命周期而消亡,如果是动态内存申请的则不会。这是要注意的点,如果是在被调函数中定义的字符串在函数调用完毕后再打印会乱码的!
中级阶段
课时十
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#define bool int
#define true 1
#define false 0
typedef int ElemType;
//数组类型
struct myList{
ElemType data;
struct myList* next;
};
typedef struct myList myList;
//随机插入
bool random_insert(myList* head,int i,ElemType e){
myList *p=head;
int j=0;
for(;p!=NULL,j<i-1;j++){
p=p->next;
}
if(p!=NULL){
myList *q=(myList*)malloc(sizeof (myList));
q->data=e;
q->next=p->next;
p->next=q;
return true;
}else{
return false;
}
}
void print_list(myList *head);
myList* index_search(myList *head,int i){
if(i<=0){
printf("false");
}
myList *p=head;
int j=0;
// 循环终止条件如果有多个的话需要用逻辑表达式连接
// 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
for(;p->next!=NULL&&j<i-1;j++){
p=p->next;
}
if(p->next==NULL){
printf("false");
}else{
myList *q=p->next;
p->next=p->next->next;
print_list(head);
free(q);
}
}
//遍历链表
void print_list(myList *head){
for (myList *p=head;p->next!=NULL;p=p->next){
printf("%3d",p->next->data);
}
printf("\n");
}
int main() {
// 创建一个头结点(头结点一般不用于存储信息)
myList *head=(myList*)malloc(sizeof (myList));
head->next=NULL;
random_insert(head,1,1);
random_insert(head,2,2);
random_insert(head,3,3);
// print_list(head);
int n;
scanf("%d",&n);
random_insert(head,2,n);
print_list(head);
scanf("%d",&n);
index_search(head,n);
return 0;
}
注意点
这个题目看着代码很长自己一定要会敲!!!很重要很重要!
课时十一
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#define bool int
#define true 1
#define false 0
typedef int ElemType;
//数组类型
struct myList{
ElemType data;
struct myList* next;
};
typedef struct myList myList;
void print_list(myList *head);
//头插法
void head_insert(myList* head,ElemType e){
myList *p= (myList*)malloc(sizeof (myList));
p->data=e;
p->next=head->next;
head->next=p;
// 如果写成以下样子,将不会有效果
// head->next=p->next;
}
//尾插法
void tail_insert(myList* tail,ElemType e){
myList *p;
p=tail;
while (p->next!=NULL){
p=p->next;
}
p->next=(myList*) malloc(sizeof (myList));
p->next->data=e;
p->next->next=NULL;
}
//遍历链表
void print_list(myList *head){
for (myList *p=head;p->next!=NULL;p=p->next){
printf("%-2d",p->next->data);
}
printf("\n");
}
void PrintList(myList* L)
{
L=L->next;
while(L!=NULL)
{
printf("%d",L->data);//打印当前结点数据
L=L->next;//指向下一个结点
if(L!=NULL)
{
printf(" ");
}
}
printf("\n");
}
int main() {
// 创建一个头结点(头结点一般不用于存储信息)
myList *head1=(myList*)malloc(sizeof (myList));
head1->next=NULL;
myList *head2=(myList*)malloc(sizeof (myList));
head2->next=NULL;
int i=-1;
while(1){
scanf("%d",&i);
if(i==9999){
break;
}
head_insert(head1,i);
}
i=-1;
while(1){
scanf("%d",&i);
if(i==9999){
break;
}
tail_insert(head2,i);
}
// print_list(head1);
// print_list(head2);
PrintList(head1);
PrintList(head2);
return 0;
}
注意点
这里要注意的是头插法与尾插创建的链表在打印时是不一样的,一个是倒序打印一个是顺序打印!
课时十二
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#define bool int
#define true 1
#define false 0
typedef int ElemType;
//数组类型
struct myList{
ElemType data;
struct myList* next;
};
typedef struct myList myList;
void print_list(myList *head);
//尾插法
void tail_insert(myList* tail,ElemType e){
myList *p;
p=tail;
while (p->next!=NULL){
p=p->next;
}
p->next=(myList*) malloc(sizeof (myList));
p->next->data=e;
p->next->next=NULL;
}
//随机插入
bool random_insert(myList* head,int i,ElemType e){
myList *p=head;
int j=0;
for(;p!=NULL,j<i-1;j++){
p=p->next;
}
if(p!=NULL){
myList *q=(myList*)malloc(sizeof (myList));
q->data=e;
q->next=p->next;
p->next=q;
return true;
}else{
return false;
}
}
//按位置查找
myList* index_search(myList *head,int i){
if(i<=0){
return NULL;
}
myList *p=head;
int j=0;
// 循环终止条件如果有多个的话需要用逻辑表达式连接
// 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
for(;p->next!=NULL&&j<i-1;j++){
p=p->next;
}
return p->next;
}
//删除相应位置元素
bool delete_i(myList *head,int i){
if(i<=0){
printf("false");
}
myList *p=head;
int j=0;
// 循环终止条件如果有多个的话需要用逻辑表达式连接
// 不可以使用逗号连接,用逗号连接遵循逗号表达式使用规则
for(;p->next!=NULL&&j<i-1;j++){
p=p->next;
}
if(p->next==NULL){
printf("false");
}else{
myList *q=p->next;
p->next=p->next->next;
print_list(head);
free(q);
}
}
//遍历链表
void print_list(myList *head){
if(head->next==NULL){
printf("null!!!");
}
for (myList *p=head;p->next!=NULL;p=p->next){
printf("%3d",p->next->data);
}
printf("\n");
}
void print(myList *p){
if(p!=NULL){
printf("%d\n",p->data);
}else{
printf("null\n");
}
}
int main() {
// 创建一个头结点(头结点一般不用于存储信息)
myList *head=(myList*)malloc(sizeof (myList));
head->next=NULL;
int n;
while (1){
scanf("%d",&n);
if (n==9999){
break;
}
tail_insert(head,n);
}
print(index_search(head,2));
random_insert(head,2,99);
print_list(head);
delete_i(head,4);
return 0;
}
注意点
如果前面两个掌握了那么这个题目难不住!
课时十三
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include<stdlib.h>
#define MaxSize 5
#define bool int
#define true 1
#define false 0
typedef int ElemType;
//数组类型
struct myList{
ElemType data[MaxSize];
int top;
};
typedef struct myList myList;
bool insert_stack(myList *stack,ElemType e){
if (stack->top==MaxSize-1){
return false;
}
stack->data[++stack->top]=e;
return true;
}
ElemType pop_stack(myList *stack){
if(stack->top==-1){
return false;
}
return stack->data[stack->top--];
}
struct myList1{
ElemType data[MaxSize];
int font;
int tail;
int maxsize
};
typedef struct myList1 myList1;
//这样写,最后一个位置是留空的
bool push_queue(myList1 *tail,ElemType e){
if((tail->tail+1)%tail->maxsize==tail->font){
printf("false\n");
return false;
}
tail->data[tail->tail]=e;
tail->tail=(tail->tail+1)%tail->maxsize;
return true;
}
ElemType pop_queue(myList1 *queue){
if(queue->tail==queue->font){
return false;
}
ElemType e;
e=queue->data[queue->font];
queue->font=(queue->font+1)%queue->maxsize;
return e;
}
int main() {
myList *stack=(myList*)malloc(sizeof (myList));
stack->top=-1;
int a;
for(int i;i<3;i++){
scanf("%d",&a);
insert_stack(stack,a);
}
while(stack->top!=-1){
printf(" %d", pop_stack(stack));
}
printf("\n");
myList1 *queue=(myList1*)malloc(sizeof (myList1));
queue->font=queue->tail=0;
queue->maxsize=MaxSize;
for(int i=0;i<5;i++){
scanf("%d",&a);
push_queue(queue,a);
}
// if(!flag){
// printf("false\n");
// }
while(queue->font!=queue->tail){
printf(" %d", pop_queue(queue));
}
return 0;
}
课时十四
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include <stdlib.h>
//基础元素类型
#define ElementData char
#define ElementDataEnd '\n'
struct BiTNode{
ElementData data;
struct BiTNode *leftNode;
struct BiTNode *rightNode;
};
typedef struct BiTNode BiTNode;
//辅助队列(通过这个队列层次建树)
struct auxiliary{
// 指向二叉树中的节点
struct BiTNode* p;
struct auxiliary *next;
};
typedef struct auxiliary tagQueue;
//封装函数初始化一个根节点
BiTNode* newNode(ElementData e){
BiTNode *pnew=(BiTNode*) malloc(sizeof (BiTNode));
pnew->leftNode=NULL;
pnew->rightNode=NULL;
pnew->data=e;
return pnew;
}
tagQueue* newTagNode(BiTNode* pnew){
tagQueue *p=(tagQueue *) malloc(sizeof (tagQueue));
p->next=NULL;
p->p=pnew;
return p;
}
// -------------------层序建树------------------------------//
BiTNode *Sequence_tree_building(){
BiTNode *tree=NULL,*pnew=NULL;
tagQueue *tail=NULL,*tagQ=NULL,*p;
ElementData e;
while(scanf("%c",&e)){
if(e==ElementDataEnd){
break;
}
//将信息写入新生成的节点
pnew=newNode(e);
p=newTagNode(pnew);
// 写成NULL==tail是为了防止tail=NULL的情况发生;
//改变指针之间的关系,将节点插入相应位置
if(NULL==tree){
//此分支创建二叉树,创建辅助队列
tree=pnew;
tail=p;
tagQ=tail;
continue;
}else{
//将新节点添加到队尾
tail->next=p;
tail=tail->next;
}
// 精妙之处,通过辅助队列构建二叉树
if(tagQ->p->leftNode==NULL){
tagQ->p->leftNode=pnew;
}else if(tagQ->p->rightNode==NULL){
// 此分支多一句是因为,这种建树方式是层序建树(这颗子树左右都有的话会向兄弟树根偏移,而辅助队列下一个就是本层的兄弟树根)
tagQ->p->rightNode=pnew;
tagQ=tagQ->next;
}
}
return tree;
}
// ---------------先序遍历----------------//
void Pre_Consult(BiTNode* tree){
if(tree==NULL){
return;
}
printf("%c",tree->data);
Pre_Consult(tree->leftNode);
Pre_Consult(tree->rightNode);
}
// ---------------------------------------------------------------------------------//
int main() {
BiTNode *tree=Sequence_tree_building();
// 前序遍历
Pre_Consult(tree);
printf("\n");
return 0;
}
作业2
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include <stdlib.h>
//基础元素类型
#define ElementData char
#define ElementDataEnd '\n'
struct BiTNode{
ElementData data;
struct BiTNode *leftNode;
struct BiTNode *rightNode;
};
typedef struct BiTNode BiTNode;
//辅助队列(通过这个队列层次建树)
struct auxiliary{
// 指向二叉树中的节点
struct BiTNode* p;
struct auxiliary *next;
};
typedef struct auxiliary tagQueue;
//封装函数初始化一个根节点
BiTNode* newNode(ElementData e){
BiTNode *pnew=(BiTNode*) malloc(sizeof (BiTNode));
pnew->leftNode=NULL;
pnew->rightNode=NULL;
pnew->data=e;
return pnew;
}
tagQueue* newTagNode(BiTNode* pnew){
tagQueue *p=(tagQueue *) malloc(sizeof (tagQueue));
p->next=NULL;
p->p=pnew;
return p;
}
// -------------------层序建树------------------------------//
BiTNode *Sequence_tree_building(){
BiTNode *tree=NULL,*pnew=NULL;
tagQueue *tail=NULL,*tagQ=NULL,*p;
ElementData e;
while(scanf("%c",&e)){
if(e==ElementDataEnd){
break;
}
//将信息写入新生成的节点
pnew=newNode(e);
p=newTagNode(pnew);
// 写成NULL==tail是为了防止tail=NULL的情况发生;
//改变指针之间的关系,将节点插入相应位置
if(NULL==tree){
//此分支创建二叉树,创建辅助队列
tree=pnew;
tail=p;
tagQ=tail;
continue;
}else{
//将新节点添加到队尾
tail->next=p;
tail=tail->next;
}
// 精妙之处,通过辅助队列构建二叉树
if(tagQ->p->leftNode==NULL){
tagQ->p->leftNode=pnew;
}else if(tagQ->p->rightNode==NULL){
// 此分支多一句是因为,这种建树方式是层序建树(这颗子树左右都有的话会向兄弟树根偏移,而辅助队列下一个就是本层的兄弟树根)
tagQ->p->rightNode=pnew;
tagQ=tagQ->next;
}
}
return tree;
}
void Layer_Consult(BiTNode* tree){
tagQueue *head=(tagQueue*) malloc(sizeof (tagQueue)),*tail,*q;
head->p=tree;
head->next=NULL;
tail=head;
while (head!=NULL){
printf("%c",head->p->data);
//入队
if(head->p->leftNode!=NULL){
tagQueue *p=(tagQueue*) malloc(sizeof (tagQueue));
p->p=head->p->leftNode;
p->next=NULL;
tail->next=p;
tail=p;
}
if(head->p->rightNode!=NULL){
tagQueue *p=(tagQueue*) malloc(sizeof (tagQueue));
p->p=head->p->rightNode;
p->next=NULL;
tail->next=p;
tail=p;
}
q=head;
head=head->next;
free(q);
q=NULL;
}
}
// ---------------------------------------------------------------------------------//
// ---------------中序遍历----------------//
void Middle_Consult(BiTNode* tree){
if(tree==NULL){
return;
}
Middle_Consult(tree->leftNode);
printf("%c",tree->data);
Middle_Consult(tree->rightNode);
}
// ---------------后序遍历----------------//
void Last_Consult(BiTNode* tree){
if(tree==NULL){
return;
}
Last_Consult(tree->leftNode);
Last_Consult(tree->rightNode);
printf("%c",tree->data);
}
int main() {
BiTNode *tree=Sequence_tree_building();
// 前序遍历
Middle_Consult(tree);
printf("\n");
Last_Consult(tree);
printf("\n");
Layer_Consult(tree);
printf("\n");
return 0;
}
课时十五
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
#include <stdlib.h>
#define ElementData int
#define ElementDataEnd -1
//二叉树的节点
struct BiTNode{
ElementData data;
struct BiTNode *leftNode;
struct BiTNode *rightNode;
};
typedef struct BiTNode BiTNode;
#define bool int
#define true 1
#define false 0
#define MaxSize 10
//初始化二叉排序树----------循环实现方式
BiTNode *Creat_BST(ElementData *a,int len){
BiTNode *tree=(BiTNode*)malloc(sizeof (BiTNode));
tree->data=a[0];
tree->rightNode=tree->leftNode=NULL;
for(int i=1;i<len;i++){
BiTNode *p=tree;
BiTNode *q=(BiTNode*) malloc(sizeof (BiTNode));
q->data=a[i];
q->leftNode=q->rightNode=NULL;
// 用于保留p指针的位置
BiTNode *prep=NULL;
while (p!=NULL){
prep=p;
if(p->data>q->data){
p=p->leftNode;
}else{
p=p->rightNode;
}
}
// 将值插入找出的位置;
prep->data > q->data?(prep->leftNode = q):(prep->rightNode = q);
// 下面这种写法是错误的
// prep->data > q->data?prep->leftNode = q:prep->rightNode = q;
}
return tree;
}
//二分查找
int Bin_Search(int *a,int len,int e){
int l,r,middle;
l=0;
r=len-1;
while (l<=r){
middle=(l+r)/2;
if(a[middle]==e){
return middle ;
} else if(a[middle]>e){
// 这里之所以这么确定,是因为middle指向的地方不是我们所要的值
r=middle-1;
}else{
l=middle+1;
}
}
return -1;
}
void PrintBST(BiTNode *tree,ElementData *d,int *p){
if(NULL==tree){
return;
}
PrintBST(tree->leftNode,d,p);
d[(*p)++]=tree->data;
printf("%3d",tree->data);
PrintBST(tree->rightNode,d,p);
}
int main() {
BiTNode *tree=NULL;
ElementData a[MaxSize]={22,1,33,13,45,31,65,221,857,3};
ElementData b[MaxSize];//用于接收二叉排序树中序遍历的值
for (int i=0;i<10;i++){
scanf("%d",&a[i]);
// printf("%d",a[i]);
}
// 构建二叉排序树
tree=Creat_BST(a,MaxSize);
int p=0;
// 在这个函数中这种写法,数组元素填充顺序是与元素打印的顺序一样的。
PrintBST(tree,b,&p);
printf("\n");
printf("%d",Bin_Search(b,MaxSize,21));
return 0;
}
注意点
依赖于二叉排序树的特性,在中序遍历该树的时候序列是有序的!
课时十六
题目描述
AC代码
// 十大排序
//https://www.cnblogs.com/onepixel/articles/7674659.html
/*
*
排序类型
考研大题:
冒泡√
快速
插入
选择√
堆
归并
*/
#include<stdlib.h>
#include<stdio.h>
#define maxSize 10//数组最大容量
char MyMenu();
//随机生成10个数
//int* initarray() {//--------------随机生成数据,1-100
// srand((unsigned)time(NULL));
// int *p=(int*) malloc(sizeof (int)*maxSize);
// for (int i = 0;i < maxSize;i++) {
// p[i] = rand() % numWide;
// }
// return p;
//}
//打印排序好的数
void printMyarray(int myarray[]) {//-----------打印数据
for (int i = 0;i < maxSize;i++) {
printf("%3d",myarray[i]);
}
printf("\n");
}
//冒泡
//针对循环条件有下列解释
//一个数据一个数据向后冒泡(外层循环是一共需要排序的元素个数剩一个的时候就不用循环了)
//内层循环是两两相邻元素进行比较(后面已经排好i个元素了),当循环到倒数第二个元素时,整个数组都扫描过了
//冒泡思想:
//每次对比相邻两个元素,大的向后移,每循环一轮将会冒出当前最大元素。
//如此循环n-1轮便可以将整个序列变的有序。
void BubbleSort(int *p){
for(int i=0;i<maxSize-1;i++){
for (int j=0;j<maxSize-i-1;j++){
if(p[j]>p[j+1]){
int temp=p[j];
p[j]=p[j+1];
p[j+1]=temp;
}
}
}
}
//插入
//针对插入排序循环条件
//外层是因为有可能第一个元素就是最大的,需要插入n-1次才能完成有序
//内层循环是因为要向前寻找可插入的位置,插入之前要先移动元素腾出位置
//当腾出位置之后在腾出的位置插入当前元素p[j+1]=temp;这么写的原因是
//p[j]不需要移动,而p[j+1]=p[j+2],p[j+1]就是我们要插入的位置
//针对算法思想:
//插入排序每一次选出一个元素,然后向序列头部方向寻找插入位置,因为要插入元素
//所以数组的话需要先移动元素,当找到合适的位置时将选出的元素插入,插入之后
//形成一个新的有序序列,然后寻找下一个元素可插入的位置,当有n-1个元素插入成功
//之后序列整体就变的有序了。
void InsertSort(int *p){
for(int i=1;i<maxSize;i++){
int temp=p[i];
int j=i-1;
while (j>=0&&p[j]>temp){
p[j+1]=p[j];
j--;
}
p[j+1]=temp;
}
}
//快速排序
//函数说明
//initFastSort函数负责将该段元素根据首元素划分为两段,并将首元素放在合适的位置
//使得首元素左边比其小右边比其大。(遍历一遍找出序列中一个元素的有序位置)
//FastSort函数的作用是将序列分而治之,每划分一次排序的次数就减半,当划分到只有一个元素在一组时
//排序顺势完成。
//算法思想
//解决掉要想让整体有序,需要先让每一段有序,当每一段有序之后整体就有序了。
int initFastSort(int *p,int l,int r){
int temp=p[l];
while(l<r){
while (l<r&&p[r]>=temp)
--r;
p[l]=p[r];
while (l<r&&p[l]<=temp)
++l;
p[r]=p[l];
}
p[l]=temp;
return l;
}
void FastSort(int *p,int l,int r){
if(l<r){
int mid=initFastSort(p,l,r);
FastSort(p,l,mid-1);
FastSort(p,mid+1,r);
}
}
void StartFastSort(int *p){
FastSort(p,0,maxSize-1);
}
int main(){
int *p=(int*) malloc(sizeof (int)*maxSize);
for (int i=0;i<10;i++){
scanf("%d",&p[i]);
}
// --------------------------------------冒泡排序
int *p1=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
p1[i]=p[i];
}
BubbleSort(p1);
printMyarray(p1);
// --------------------------------------快速排序
int *p2=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
p2[i]=p[i];
}
StartFastSort(p2);
printMyarray(p2);
// --------------------------------------插入排序
int *p3=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
p3[i]=p[i];
}
InsertSort(p3);
printMyarray(p3);
return 0;
}
课时十七
作业1
题目描述
AC代码
// 十大排序
//https://www.cnblogs.com/onepixel/articles/7674659.html
/*
*
排序类型
考研大题:
冒泡√
快速
插入
选择√
堆
归并
*/
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define maxSize 10//数组最大容量
#define numWide 100//随机生成数据的范围
//打印排序好的数
void printMyarray(int myarray[]) {//-----------打印数据
for (int i = 0;i < maxSize;i++) {
printf("%3d",myarray[i]);
}
printf("\n");
}
//选择
//针对选择排序循环条件
//每次找出一个位置,然后拿其余元素与其对比找出目前无序序列中最大或最小的元素放在选出的位置
//需要经过n-1次筛选(所以外层循环为n-1)
//从选出位置的下一个元素开始对比,直到列表中无序部分的末尾(所以内层循环那样写)
//针对算法思想:
//选择排序每次选出一个最大的元素或者最小的元素(看升序还是降序),放在当前无序的部分的第一个位置
//每选出一个就将有序部分向后扩展一位,继续选元素,直到整个序列有序。
void SelectSort(int *p){
for(int i=0;i<maxSize-1;i++){
for(int j=i+1;j<maxSize;j++){
if(p[i]>p[j]){
int temp=p[i];
p[i]=p[j];
p[j]=temp;
}
}
}
}
//归并排序用到的合并函数
//在写这个函数的时候一定要注意,开始结束条件不再是0与len-1了,而是从外部传进来的索引
void Merger(int *p,int l,int midde,int r){
static int B[maxSize];
int i=0,j=0,z=0;
//最后将pB中的元素放进p;
for(i=l;i<=r;i++){
B[i]=p[i];
}
for(i=l,j=midde+1,z=l;i<=midde&&j<=r;z++){
if(B[i]<B[j]){
p[z]=B[i];
i++;
}else{
p[z]=B[j];
j++;
}
}
while(j<=r){
p[z++]=B[j++];
}
while(i<=midde){
p[z++]=B[i++];
}
}
//归并排序
//归并排序思想:
//归并排序有许多种类型,常考的就是路归并,先分组刚开始
//一组一个元素,然后将分的组逐步两两合并,最后得到有序序列
//本函数传进来的是数列的左右下标。
void MergerSort(int *p,int l,int r){
if(l<r){
// 这个midde始终指向中间位置
int midde=(l+r)/2;
MergerSort(p,l,midde);
MergerSort(p,midde+1,r);
//合并序列
Merger(p,l,midde,r);
}
}
//堆排序
//排序思想:
//先将数据初始化成为大根堆或者小根堆的形式(大根堆是大的在作为父节点,小根堆是小的作为父节点)
//大根堆用于升序排序,小根堆用于降序
//初始化完毕之后,开始选择元素,每次选出根节点元素,然后重新生成大根堆
//(这里需要注意的是生成大根堆之后选择元素时最大只需要遍历到树的深度即可)
//调整大根堆的函数(每次只调节一颗树)k为当前根节点元素所在的下标(maxIndex是最大的剩余长度)
//这里的maxIndex限制条件是严格的(如果在判断的时候小了或者大了,均会造成数据混乱)
//所以记住,当选出一个元素的之后,需要将这个元素移到有序段开头,并及时把无序的部分长度减1.
void DeliverBigHeap(int *p,int k,int maxIndex){
int sonIndex=k*2+1;
while (sonIndex<=maxIndex){
if(sonIndex+1<=maxIndex&&p[sonIndex]<p[sonIndex+1]){
sonIndex++;
}
if(p[k]<p[sonIndex]){
int temp=p[k];
p[k]=p[sonIndex];
p[sonIndex]=temp;
// 交换之后继续探测上一个根节点
k=sonIndex;
sonIndex=k*2+1;
}else{
break;
}
}
}
void HeapSort(int *p,int len){
int temp;
for(int i=(len-1)/2;i>=0;i--){
DeliverBigHeap(p,i,len-1);
}
// temp=p[len-1];
// p[len-1]=p[0];
// p[0]=temp;
// printMyarray(p);
//---------------------------------写法1
// int i;
// for(i=len-1;i>0;i--){
// temp=p[i];
// p[i]=p[0];
// p[0]=temp;
// //
// DeliverBigHeap(p,0,i-1);
// }
// temp=p[i];
// p[i]=p[0];
// p[0]=temp;
//----------------------------------写法2
temp=p[len-1];
p[len-1]=p[0];
p[0]=temp;
for(int i=len-2;i>0;i--){
DeliverBigHeap(p,0,i);
temp=p[i];
p[i]=p[0];
p[0]=temp;
}
//----------------------------------错误写法
//错误原因:因为在调整大根堆的时候实际边界是i-1,这里写成i了
//这在一定情况下容易造成已经排好序的元素再回到树中,然后占据不该占据的位置。
// for(int i=len-2;i>0;i--){
// temp=p[i];
// p[i]=p[0];
// p[0]=temp;
// DeliverBigHeap(p,0,i);
// }
// temp=p[len-1];
// p[len-1]=p[0];
// p[0]=temp;
}
int main(){
int *p=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
scanf("%d",&p[i]);
}
// --------------------------------------选择排序
int *p1=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
p1[i]=p[i];
}
SelectSort(p1);
printMyarray(p1);
int *p2=(int*) malloc(sizeof (int)*maxSize);
// --------------------------------------堆排序
for(int i=0;i<10;i++){
p2[i]=p[i];
}
HeapSort(p2,maxSize);
printMyarray(p2);
return 0;
}
作业2
题目描述
AC代码
// 十大排序
//https://www.cnblogs.com/onepixel/articles/7674659.html
/*
*
排序类型
考研大题:
冒泡√
快速
插入
选择√
堆
归并
*/
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define maxSize 10//数组最大容量
#define numWide 100//随机生成数据的范围
//打印排序好的数
void printMyarray(int myarray[]) {//-----------打印数据
for (int i = 0;i < maxSize;i++) {
printf("%3d",myarray[i]);
}
printf("\n");
}
void Merger(int *p,int l,int midde,int r){
static int B[maxSize];
int i=0,j=0,z=0;
//最后将pB中的元素放进p;
for(i=l;i<=r;i++){
B[i]=p[i];
}
for(i=l,j=midde+1,z=l;i<=midde&&j<=r;z++){
if(B[i]<B[j]){
p[z]=B[i];
i++;
}else{
p[z]=B[j];
j++;
}
}
while(j<=r){
p[z++]=B[j++];
}
while(i<=midde){
p[z++]=B[i++];
}
}
void MergerSort(int *p,int l,int r){
if(l<r){
// 这个midde始终指向中间位置
int midde=(l+r)/2;
MergerSort(p,l,midde);
MergerSort(p,midde+1,r);
//合并序列
Merger(p,l,midde,r);
}
}
int main(){
int *p=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
scanf("%d",&p[i]);
}
// --------------------------------------选择排序
int *p1=(int*) malloc(sizeof (int)*maxSize);
for(int i=0;i<10;i++){
p1[i]=p[i];
}
MergerSort(p1,0,maxSize);
printMyarray(p1);
return 0;
}
高级阶段
课时十九
作业1
题目描述
AC代码
//
// Created by Zhu Shichong on 2023/1/9.
//
#include <stdio.h>
int main() {
int a;
scanf("%d",&a);
printf("%2d\n",a<<1);
printf("%2d\n",a>>1);
return 0;
}
注意点
算术左移相当于乘以2,算术右移相当于除以2.
作业2
题目描述
AC代码
#include<stdio.h>
int main(){
int p[5];
int ans=0;
for(int i=0;i<5;i++){
scanf("%d",&p[i]);
ans=ans^p[i];
}
printf("%d",ans);
}
注意点
这个借助一个条件,0与任何数异或结果还是那个数本身,任何数与本身异或结果为0。
课时二十
题目描述
AC代码
print(" 0 13")
注意点
这个题目用手算应该不好算的,直接用Clion定义一个float变量值为1.456,然后计算一下两个值即可!
课时二十一
题目描述
AC代码
print("mov\npush\npop")
注意点
无,汇编语言基础知识。