把之前立下的flag补完,太懒了,有好多好多东西没写。
小战士过火线
/**
* 通过逆操作来复原
*
* 因为要进行尾删除和头插入操作,所以采取链表来来存储
*/
#include <stdio.h>
#include <stdlib.h>
/* 存储战士信息 */
typedef struct node
{
int value; //1代表老战士,2代表新战士
struct node *next;
} NODE;
typedef NODE *List;
List init(); //初始化队列
int deleteLastNode(List L); //删除并返回最后在一个值
void addNode(List L, int value); //在对头添加一个节点
void printAns(List L); //打印结果
int main()
{
List L = init();
for (int i = 0; i < 4; i++)
{
addNode(L,deleteLastNode(L)); //把最后一个节点移动到开头
addNode(L,0); //先是小战士
addNode(L,1); //再是老战士
}
printAns(L);
return 0;
}
List init() //初始化队列
{
/* 申请一个头节点 */
List L = (List)malloc(sizeof(NODE));
L->next = NULL;
L->value = -1;
/* 加入101 */
addNode(L,1);
addNode(L,0);
addNode(L,1);
return L;
}
int deleteLastNode(List L) //删除并返回最后在一个值
{
List p = L;
/* 找到队尾 */
while (p->next->next != NULL) //这里链表至少要有俩个节点
{
p = p->next;
}
List q = p->next;
int tmp = q->value; //保存返回值
p->next = q->next;
free(q);
return tmp;
}
void addNode(List L, int value) //在对头添加一个节点
{
List p = (List)malloc(sizeof(NODE));
p->value = value;
p->next = L->next;
L->next = p;
}
void printAns(List L) //打印结果
{
L = L->next;
while(L)
{
printf("%d",L->value);
L = L->next;
}
}
静态链表
/**
* 静态链表相比较于普通的链表可以减少 malloc的操作
* 但是也需要事先知道大小,顺序表的特点
* 可以比较快速的实现插入和删除的操作,链式表的特点
*
* 适合那些已知最大数据量的表
* ps:它能做到的,链表都能做到
*
* 0是空的链表池
* 1是头节点
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int value; //数据
int next; //下一个
} NODE;
typedef NODE *List;
List init(int size); //根据大小初始化
void addNode(List L, int value); //添加元素
void deleteNode(List L, int value); //删除元素
int isFull(List L); //是否满了
void printList(List L); //打印
int main()
{
List L = init(20);
char op;
int value;
//测试
// for(int i=1;i<22;i++)
// {
// addNode(L,i);
// }
// printList(L);
// for(int i=5;i<15;i++)
// {
// deleteNode(L,i);
// }
// printList(L);
// for(int i=1;i<22;i++)
// {
// addNode(L,i);
// }
// printList(L);
/* 测试 */
while (op = getchar(), op != 'q')
{
switch (op)
{
case 'a':
{
scanf("%d",&value);
getchar();//读取回车
addNode(L,value);
};break;
case 'd':
{
scanf("%d",&value);
getchar();//读取回车
deleteNode(L,value);
};break;
case 'p':
{
getchar();//读取回车
printList(L);
};break;
case 'f':
{
getchar();//读取回车
printf("is full?%s\n",isFull(L)?"yess":"no");
};break;
default:
break;
}
}
return 0;
}
List init(int size) //根据大小初始化
{
List L = (List)malloc(sizeof(NODE)*(size+2));//俩个头节点
L[1].next = L[size+1].next = 0;//0作为终止标识
L[0].next = 2;
for(int i=2;i<size+1;i++)
{
L[i].next = i+1;
}
return L;
}
void addNode(List L, int value) //添加元素
{
/* 检查是不是满了 */
if(isFull(L))
{
printf("已经满了,插入失败\n");
return;
}
/* 插入操作 */
/* 取空的节点 */
int p = L[0].next;
L[0].next = L[p].next;
/* 在头部插入 */
L[p].value = value;
L[p].next = L[1].next;
L[1].next = p;
}
void deleteNode(List L, int value) //删除元素
{
/* 指向要删除的元素 */
int p = 1;
while (L[p].next != 0 && L[L[p].next].value != value )
{
p = L[p].next;
}
/* 没找到 */
if(L[p].next == 0)
return;
/* 删除操作 */
int q = L[p].next;
L[p].next = L[q].next;
L[q].next = L[0].next;
L[0].next = q;
}
int isFull(List L) //是否满了
{
return L[0].next == 0;
}
void printList(List L) //打印
{
int p = L[1].next;
while (p)
{
printf("%d ",L[p].value);
p = L[p].next;
}
putchar('\n');
}
打印字符串
/**
* 利用类似于深度优先的方法打印所有的字符串
*
* 1.启发函数,来调动,按顺序选取第一个值,加标记
* 2.在剩下的值里面挑选,知道长度符合要求
*
* @2020/1/09
* 果然憨憨遇到的都是憨憨
*/
#include <stdio.h>
/* 全局变量 */
int visited[26];//标记是不是访问过了
char curAns[27];
int cnt;//检查是否正确 注意:这里的输出是字母只使用一次的 不存在aaa这种,
//长度为3的所有组合为 26 + 26*25 + 26*25*24
void slove(int maxLenth);//启动函数
void DFS(int curLenth,int endLenth);//深度搜索
void printAns();//打印
int main()
{
int maxLenth;
scanf("%d",&maxLenth);
slove(maxLenth);
printf("cnt: %d\n",cnt);
return 0;
}
void slove(int maxLenth)//启动函数
{
for(int i=1;i<=maxLenth;i++)
{
for(int j=0;j<26;j++)
{
visited[j] = 1;
curAns[0] = j + 'a';
DFS(1,i);
visited[j] = 0;
}
}
}
void DFS(int curLenth,int endLenth)//深度搜索
{
/* 是否已经达到目标 */
if(curLenth == endLenth) //退出
{
curAns[endLenth] = '\0';
printAns();
return;
}
for(int i=0;i<26;i++)
{
if(!visited[i]) //没有被访问
{
visited[i] = 1;
curAns[curLenth] = i + 'a';
DFS(curLenth+1,endLenth);
visited[i] = 0;
}
}
}
void printAns()//打印
{
puts(curAns);
cnt++;
}
出栈顺序
/**
* 有好多种思路,采用比较好接受的俩种
*
* 1.模拟
* 1.创建一个栈
* 2.初始化(压栈到栈顶是当前的元素)
* 3.出栈
* 4.检查栈顶是不是要出栈的元素
* 如果是,到3
* 如果不是,那么判断是不是可以压栈到达
* 可以压栈,到3
* 不可以,那么退出
* 2.逻辑检测
* 就是一个出栈顺序abcde,a后面小于a的值一定要符合逆序
*
* @2020/1/9
* ps:大一的妹纸果然比我认真多了
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 1000 //判断的大小
int slove1(int array[],int n);//第一种方法
int slove2(int array[],int n);//第二种方法
int main()
{
/* 获取输入 */
int n;
while (scanf("%d",&n),n>0)
{
int* array = (int*) malloc(sizeof(int)*n);
for(int i=0;i<n;i++)
scanf("%d",&array[i]);
printf("1:isOk?%s \n",slove1(array,n)?"yes":"no");
printf("2:isOk?%s \n",slove2(array,n)?"yes":"no");
free(array); //多次重复,所以写一个释放
}
return 0;
}
int slove1(int array[],int n)//第一种方法
{
int stack[MAX_N];
int tail = 0;//指向栈顶的下一个
int max = 1;
for(int i=0;i<n;i++) //要出栈n次
{
while(tail==0 || stack[tail-1] != array[i]) //不符合出栈的需要
{
if(max > array[i])//入栈的值大于需要入栈的值
return 0;
else
stack[tail++] = max++;
}
tail--;//出栈
}
return 1;
}
int slove2(int array[],int n)//第二种方法
{
int max = 0;
for(int i=0;i<n;i++)
{
if(array[i] < max && array[i]>array[i-1])
return 0;
max = max > array[i]?max:array[i];
}
return 1;
}
图的基本操作
/**
* 先插眼,写下思路,以后再补充吧。
*
* 1.图的存储结构
* a.矩阵存储,比较奢侈,适合边特别多的情况,以及数据量小的情况(不必考虑效率)
* b.邻接表,较好实现,不易出错
* c.十字链表,效率高,但是不太好写
*
* 2.拓扑排序
* 辅助数组存储各个几点的入度
* 辅助栈
* 1.统计各个节点的入度
* 2.将入度为0的节点压栈
* 3.挑一个入度为0的节点输出,并改变其进入的节点的入度,若为0,压栈
* 4.重复3,直达栈空(如果有环的话,栈空了,但是打印的节点数不够)
*
* 3.反转
* 比较简单的是重新开一个G,然后添加
*
* 4.最小生成树
* Prime:
* 将节点分为俩类,一类是已入树的(A),一类是未入树的(B)
* 辅助数组记录B种节点与A的距离
* 1.随便取一个点x,入A
* 2.改变B中与x有关的节点的距离
* 3.挑选辅助数组里距离最近的点,(看起来得用一个优先队列),入A,重复2,直到B空
*
* Fraskal:
* 辅助数组记录边的距离
* 1.挑选最短的边,得到俩个相关节点a,b
* 2.判断a,b是不是连通
* 如果是,重复1
* 如果不是,将a,b所对应的图链接(并查集),重复1
*
* 4.最短路径
* Dijstra:
* 辅助数组记录v到该点的最短距离
* 1.挑一个最短的距离,找到对应点a
* 2.判断a是否已经连通
* 如果是,重复1
* 如果不是,那么将a连入,更新与a有关的点的距离,重复1,直到遇到要求的点
*
* Floyd:
* dp[i][j] 从i到j的最短距离
* for(插入点k)
* for (起始点x)
* for (终止点y)
* 插入点k是否能使x到y的距离变小
* ps:为了防止溢出,先判断一下是不是联通
* dis = dp[i][k] == MAX || dp[k][j] == MAX ? MAX: dp[i][k] + dp[k][y];
* dp[i][j] = dp[i][j] < dis ? dp[i][j]:dis;
*
*
*
*
* 5.求关键路径
* 准备:
* a.拓扑序
* b.反转
* 1.求最早开始时间 t1
* 2.求最晚开始时间 t2
* 3.时间 t3 = 最晚开始时间 - 工作所需时间
* 4. t1 == t3 的点就是关键路径上的点
*
* 6.求关节点,这个太玄乎了,还没搞懂
*
* @2020/1/10
* 打了鸡血补上代码
*/
一笔画求解
/**
* 对于这种试验型的问题,其实大多数靠直觉和运气,去年回家小侄女老是要我帮她做这个
* 开始还行,后来就越来越玄乎了,今年回家前写一个,让她看看我的厉害,啧啧啧
*
* 为了方便,利用矩阵存储,对于某些问题需要经过俩次的,可以 G[i][j] = n
*
* @2020/1/10
* 先写个思路,明天实现
* 1.建立图,输入 x y (n) 如过没有n 那么默认是1,这个倒是可以利用getchar 判断是空格是不是来实现
* 记录一下边的数目
* 3.拷贝图
* 2.对每一个节点开始DFS,走过一次边,就-1,直到没有边可走,判断是不是走了所有的边(利用边的数目)
*
*
*/
#include <stdio.h>
#define MAX_N 20 //20个节点
/* 全局变量 */
int gPre[MAX_N][MAX_N]; //保存最开始的输入
int gCur[MAX_N][MAX_N]; //保存当前的结果
int totalE; //总边数,用来判断是不是走完了
int totalV; //总的节点数
int path[MAX_N * 2]; //记录路径,这里×2考虑到有些是要走俩次的
int pathLenth; //指向路径尾
void getInfo();//获取输入,返回一下节点数目
void initInfo();//初始化数据
int DFS(int x,int deep);//搜索
void printPath();//打印路径
int main()
{
while(1)
{
int flag=0;
getInfo();
for(int i=0;i<totalV;i++)
{
initInfo();
path[0] = i;
pathLenth = 1;
if(DFS(i,1))
{
printPath();
flag = 1;
break;//只打印一种
}
}
if(!flag)
printf("生成失败是不是,输入出错了啊?\n");
}
return 0;
}
void getInfo()//获取输入,返回一下节点数目
{
printf("请输入节点数: ");
scanf("%d",&totalV);
printf("请输入边x y (数目如果不输入,默认为1) (-1 -1 表示结束): \n");
int x,y,time;
while (scanf("%d %d",&x,&y),x!=-1)
{
time = 1;
totalE++; //边数增加
char c = getchar();
if(c != '\n')
scanf("%d",&time);
gPre[x][y] = time;
gPre[y][x] = time; //无向图
}
}
void initInfo()//初始化数据
{
/* 清空路径 */
pathLenth = 1;
/* 拷贝图 */
for(int i=0;i<totalV;i++)
for(int j=0;j<totalV;j++)
gCur[i][j] = gPre[i][j];
}
int DFS(int x,int deep)//搜索
{
/* 判断是不是能退出了 */
if(deep-1 == totalE)
return 1;
/* 找x节点能走的部分 */
for(int i=0;i<totalV;i++)
{
if(gCur[x][i])
{
gCur[x][i]--;
gCur[i][x]--;
path[pathLenth++] = i;
if(DFS(i,deep+1))
return 1;
gCur[x][i]++;
gCur[i][x]++;
pathLenth--;
}
}
return 0;
}
void printPath()//打印路径
{
printf("\n\n可能行的一条路径为: ");
for(int i=0;i<pathLenth;i++)
printf("%d ",path[i]);
putchar('\n');
}
原地归并排序
/**
* 原地归并的O(1)空间复杂度实现,其实是O(logn)
*
* yw念念叨叨了一个学期的东西,啧啧啧,总算是搞懂是啥了
*
* 利用了翻转:
* 123456->561234
* 1.1234->4321 56->65 --> 432165
* 2.432165 -> 561234
* 1.先递归拆分,直到1
* 2.合并
* 3.找前段,找后段
*
*
* @2020/1/11
*/
#include <stdio.h>
#include <stdlib.h>
void swap(int array[],int a,int b);//交换俩个数
void reverse(int array[],int l,int r);//反转
void convert(int array[],int l,int m,int r);//反转
void merge(int array[],int l,int m,int r);//合并
void mergeSort(int array[],int l,int r);//合并排序启发
//int array[10];
int main()
{
/* 输入 */
int n;
scanf("%d",&n);
int* array = (int*) malloc (sizeof(int)*n);
for(int i=0;i<n;i++)
scanf("%d",&array[i]);
/* 合并 */
mergeSort(array,0,n-1);
/* 打印 */
for(int i=0;i<n;i++)
printf("%d ",array[i]);
putchar('\n');
return 0;
}
void swap(int array[],int a,int b)//交换俩个数
{
array[a] ^= array[b];
array[b] ^= array[a];
array[a] ^= array[b];
}
void reverse(int array[],int l,int r)//反转
{
while (l<r)
{
swap(array,l++,r--);
// printf("ok %d %d\n",l,r);
}
}
void convert(int array[],int l,int m,int r)//反转,从m起
{
reverse(array,l,m-1);
reverse(array,m,r);
reverse(array,l,r);
}
void merge(int array[],int l,int m,int r)//合并,这个函数极容易出错
{
int i = l;
int j = m+1;
while (i<j && j<=r)
{
while (array[i] < array[j] && i<j)
i++;
if(i==j) //第一处
break;
int index = j;
while(j<=r && array[j] <= array[i])//第二处
j++;
convert(array,i,index,j-1);
i += j-index;
}
}
void mergeSort(int array[],int l,int r)//合并排序启发
{
if(l<r)
{
mergeSort(array,l,(l+r)>>1);
mergeSort(array,(l+r)/2+1,r);
merge(array,l,(l+r)/2,r);
}
}
来源:CSDN
作者:憨皮烨
链接:https://blog.csdn.net/qq_43641752/article/details/103897724