(1)高精度加法:
遗漏知识点:
1.求字符串长度函数:#include<string.h> strlen(字符串名字)
2.字符串名字:printf("%s\n",a)
3.FOR循环语法:!!!!!!,中间是判断通过条件!!!!!!!!!
易错点:
1.大数用字符型存储,涉及到整数型的运算要记得转换。
2.加法中,缺位,补位等问题的解决。两数相加要考虑进位和缺位这两个数,和每一位的控制。
答案:
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char a[110],b[110];
int aaa[110],bbb[110],ccc[110];
int i,j,A,B,s=0,n=0;
scanf("%s",a);
scanf("%s",b);
/*printf("%s\n",a);
printf("%s",b);*/
A=strlen(a);
B=strlen(b);
/*printf("%d\n",A);
printf("%d",B);*/
for(i=A-1;i>=0;i--) aaa[i]=a[i]-'0';
for(i=B-1;i>=0;i--) bbb[i]=b[i]-'0';
for(i=A-1,j=B-1;i>=0||j>=0||s>0;i--)
{
//缺位
if(i>=0) s=s+aaa[i];
if(j>=0) s=s+bbb[j];
//存结果,从后向前
ccc[n]=s%10;
//进位
s=s/10;
j--;n++;
}
for(i=n-1;i>=0;i--)printf("%d",ccc[i]);
return 0;
}
(2)回形取数
知识点:
1.!!!!SCANF()里面放地址啊啊!!
易错点:
<思维简化>----两个数组+大循环(四个小循环不用复杂的约束)+大循环次数向上取整
1.矩阵数组避免C语言数组坐标问题,输入注意坐标:
for(i=1;i<=n;i++) //输入坐标归正
for(j=1;j<=m;j++)
scanf("%d",&st[i][j]);
答案:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int m,n;
scanf("%d%d",&m,&n);
int i,j;
int a[210][210],r[210][210]; //输入
for(i=1;i<=m;i++){ //数组坐标简化
for(j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
int q=1,num=(n+1)/2; //q记循环圈数,num记大循环限制
for(q=1;q<=num;q++) //大循环
{
for(i=q;i<=m+1-q;i++) //1
{
if(r[i][q]==0){
printf("%d ",a[i][q]);
r[i][q]=1;
}
}
for(j=q;j<=n+1-q;j++){ //2
if(r[m-q+1][j]==0){
printf("%d ",a[m-q+1][j]);
r[m-q+1][j]=1;
}
}
for(i=m-q+1;i>=q;i--){ //3
if(r[i][n-q+1]==0){
printf("%d ",a[i][n-q+1]);
r[i][n-q+1]=1;
}
}
for(j=n-q+1;j>q;j--){ //4
if(r[q][j]==0){
printf("%d ",a[q][j]);
r[q][j]=1;
}
}
}
return 0;
}
静态链表:
const int N = 10000; //按需要定义静态链表的空间大小
struct node{ //单向链表
int id; //这个结点的id
int data; //数据
int nextid; //指向下一个结点的id
}nodes[N]; //静态分配需要定义在全局
//为链表的next指针赋初值,例如:
nodes[0].nextid = 1;
for(int i = 1; i <= n; i++){
nodes[i].id = i; //把第i个结点的id就赋值为i
nodes[i].nextid = i + 1; //next指针指向下一个结点
}
//定义为循环链表:尾指向头
nodes[n].nextid = 1;
//遍历链表,沿着nextid访问结点即可
//删除结点。设当前位于位置now,删除这个结点
nodes[prev].nextid = nodes[now].nextid; //跳过结点now,即删除now
now = nodes[prev].nextid; //更新now
双向静态链表:
const int N = 10000;
struct node{ //双向链表
int id; //结点编号
int data; //数据
int preid; //前一个结点
int nextid; //后一个结点
}nodes[N];
//为结点的指针赋初值,例如
nodes[0].nextid = 1;
nodes[1].preid = 0;
for(int i = 1; i <= n; i++){ //建立链表
nodes[i].id = i;
nodes[i].preid = i-1; //前结点
nodes[i].nextid = i+1; //后结点
}
//定义为循环链表
nodes[n].nextid = 1; //循环链表:尾指向头
nodes[1].preid = n; //循环链表:头指向尾
//遍历链表,沿着preid和nextid访问结点即可
//删除结点。设当前位于位置now,删除这个结点
prev = nodes[now].preid;
next = nodes[now].nextid;
nodes[prev].nextid = nodes[now].nextid; //删除now
nodes[next].preid = nodes[now].preid;
now = next; //更新now
//插入结点,见后面的习题“自行车停放”
(3)自行车停放:
易错点:
1.链表重学一遍,全忘了
这个题的思想是:先填充数据,记录位置索引(方便搜索),先连尾,后连头
答案:
#include<stdio.h>
#include<stdlib.h>
const int N = 100000;
struct node{
int data;
int preid;
int nextid;
}nodes[N];
int locate[N];
int now;
void initNodes()
{
nodes[0].nextid=1;
nodes[1].preid=0;
now=2;
}
void insert(int k,int x) //k是此时插入的节点的前一个节点序号
{
nodes[now].data = x;
locate[x] = now;
nodes[now].nextid = nodes[k].nextid;
nodes[nodes[k].nextid].preid=now;
nodes[now].preid = k;
nodes[k].nextid = now;
now ++;
}
int main(int argc, char *argv[])
{
int n,x,y,z;
scanf("%d",&n);
initNodes();
scanf("%d",&x);
insert(0,x);
n--;
while(n--)
{
scanf("%d%d%d",&x,&y,&z);
if(z == 0) insert(nodes[locate[y]].preid,x);
else if(z == 1) insert(locate[y],x);
}
for(int i=nodes[0].nextid;i!=1;i=nodes[i].nextid)
printf("%d ",nodes[i].data);
return 0;
}
(4)队列操作:
知识点:
(1)有关队列:
队列:先进先出,插入的那端称为队尾(入队),删除的那段称为队头(出队)。
顺序队列:数组+两个指针(front指向队头元素,rear指向队尾元素) ——————>假溢出问题
循环队列(解决假溢出):使用队列首尾相连接的顺序结构(不会用出队)
//队空的条件
q.front == q.rear;
//队满的条件
(q.rear+1)%maxsize == q.front
//入队时队尾的移动
rear=(rear+1)%M;
//出队时队头的移动
front=(front+1)%M;
(2)->:
结构体指针类型的变量可以用->指向成员变量
(3)switch分支结构:
(4)指针分配空间:malloc()函数
需要调用#include<malloc.h>
答案:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
const int N = 50;
typedef struct{
int *data;
int front;
int rear;
}Queue;
Queue Q;
int initQuene() //初始化
{
Q.data = (int *)malloc(sizeof(int));
if(!Q.data) exit(0);
Q.front=Q.rear=0;
return 1;
}
void QueneNum(int n) //求队列长度
{
printf("%d\n",(Q.rear-Q.front+n)%n);
}
int EnQuene(int x,int n) //入队
{
if((Q.rear+1)%n==Q.front){ //队列满
return -1;
}
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%n;
return 1;
}
int DeQuene(int n) //出队
{
if(Q.rear==Q.front){ //队列空
printf("no");return -1;
}
printf("%d\n",Q.data[Q.front]);
Q.front=(Q.front+1)%n;
return 1;
}
int main(int argc,char *argv)
{
int n;
scanf("%d",&n); //队列长度
int stop = initQuene();
int m,x;
while(stop>0){
scanf("%d",&m); //命令
switch(m)
{
case 1:scanf("%d",&x);stop=EnQuene(x,n);break;
case 2:stop=DeQuene(n);break;
case 3:QueneNum(n);stop=1;break;
}
}
return 0;
}
(5) 栈练习题:汉诺塔
知识点:
(1)栈:(水桶)后进先出
只能在栈顶(top)进行插入和删除操作;
顺序栈:数组+栈顶(top)+栈底(base)
top指针实际指的是栈顶元素的上一个元素
const int N = 1000;
typedef struct{
int *top; //栈顶指针
int *base; //栈底指针
int stacksize; //栈的实际长度
}SqStack;
a.初始化
int intStack(SqStack &S)
{
//(1)为顺序栈分配一个最大容量为N的数组空间
S.base = (int *)malloc(N*sizeof(int));
if(!base) exit(0);
//(2)栈顶指针top初始化为base,表示栈为空
S.top=S.base;
//(3)设置栈的最大容量MAXSIZE
S.stacksize = N;
return 1;
}
b.入栈
int Push(SqStack &S,int x)
{
//(1)判断栈是否满
if(s.top-s.base == s.size) return 0;
//(2)压栈:先赋值,再上移
*S.top++=e;
return 0;
}
c.出栈
int Pop(SqStack &S)
{
//(1)判断栈是否为空
if(S.base == S.top) return 0;
//(2) 出栈
*S.top--;
return 1;
}
(2)汉诺塔算法理解:(递归)
问题实质:(递归问题)
(1)先把n以上的n-1个盘子从A杆子移到B杆子,以C为中介杆子(限制条件:n-1=1;n=2)
(2)把n盘子从A杆子移到C杆子
(3)剩下的n-1个盘子再重复以上两个动作
答案:
#include<stdio.h>
#include<stdlib.h>
int count=0;
int n,m;
void move(int n,char a,char b)
{
count++;
if(count == m){
printf("#%d: %c->%c\n",n,a,b);
}
}
void Hanoi(int n,char x,char y,char z)
{
if(n>1)
{
Hanoi(n-1,x,z,y);
move(n,x,z);
Hanoi(n-1,y,x,z);
}
else
move(n,x,z);
}
int main(int argc,char *argv[])
{
scanf("%d%d",&n,&m);
Hanoi(n,'A','B','C');
printf("%d",count);
return 0;
}
(6)二叉树练习题:FBI树
知识点:
(1)二叉树:
树:(1)有且只有一个根(2)除根节点之外,其余节点他们自成一棵树
二叉树:(1)有且只有一个根(2)除根节点外,其余节点分为两个互不相交的子集,分别称为根的左子树和右子树。
二叉树与树的区别:(1)每个节点最多两颗子树(2)子树有左右之分
二叉树的链式存储:(二叉链表)
a.二叉链表的存储表示
typedef strcut BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
b,遍历二叉树(递归)
先序遍历:(1)访问根节点 (2)先序遍历左子树 (3)先序遍历右子树
中序遍历:左子树-.>根节点->右子树
后序遍历:左子树->右子树->根节点
void InOrderTraverse(BiTreee T)
{
if(T) //若二叉树非空
{
InOrderTraverse(T->lchild);
cout<< T->data; //访问根节点
InOrderTraverse(T->rchild);
}
}
c.建立二叉链表
void CreateBiTree(BiTree &T)
{
//(1)读入字符ch
scanf("%c",&ch);
//(2)若ch为‘#’,则二叉树为空树
if(ch=='#") T=NULL;
else
{
//申请一个结点空间T
T=(char)malloc(sizeod(char));
//将ch赋给T->data
T->data = ch;
//递归创建T的左子树
CreateBiTree(T->lchild);
//递归创建T的右子树
CreateBiTree(T->rchild);
}
d.计算二叉树的深度
int Depth(BiTree T)
{
if(T==NULL) return 0; //如果是空树,深度为0,递归结束
else
{
m=Depth(T->lchild); //递归计算左子树的深度
n=Depth(T->lchild); //递归计算右子树的深度
if(m>n) return (m+1);
else return (n+1);
}
}
e.统计二叉树中节点的个数
int NodeCount(BiTree T)
{
if(T == NULL) return 0;
else return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}
2. C++ 1<<n
将左数的二进制编码想左移动n位并将空位补0
题意理解:
答案:
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
void FBI(char num[], int sum)
{
if (sum == 1)
{
if (num[0] == '0')
cout << "B";
else
cout << "I";
}
else
{
char num1[2000];
char num2[2000];
for (int i = 0; i < sum / 2; i++)
{
num1[i] = num[i];
num2[i] = num[i + (sum / 2)];
}
FBI(num1, sum / 2);
FBI(num2, sum / 2);
bool isF = false;
for (int i = 0; i < sum-1; i++)
{
if (num[i] != num[i + 1])
{
isF = true;
break;
}
}
if (isF == true)
{
cout << "F";
}
else
{
if (num[0] == '0')
cout << "B";
else
cout << "I";
}
}
}
int main()
{
int n;
cin >> n;
char num[2000];
int sum = pow(2, n);
for (int i = 0; i < sum; i++)
{
cin >> num[i];
}
FBI(num, sum);
return 0;
}
(7)蓝桥杯真题:完全二叉树的权值(2019 年省赛)(留着)
知识点:
(1)完全二叉树:深度为K的,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中编号从1至n的节点一一对应时,称之为完全二叉树。