从终端输入任意一个只包含小写字母的字符串
输出每个字符出现的次数。
如:输入:aabbccdfe
输出:a:2 b:2 c:2 d:1 e:1 f:1 g:0 h:0 .... z:0
#include
int get_index(char value){
return value -'a';
}
int main(int argc, const char *argv[])
{
char s[128] = {0};
printf("请输入字符串(小写):");
scanf("%s",s);
//用来保存字母出现次数的数组
//count[0] --> a出现的次数
//count[1] --> b出现的次数
//...
//count[25] --> z出现的次数
unsigned int count[26] ={0};
int i = 0;
int index = 0;
while(s[i]!='\0'){
index = get_index(s[i]);
count[index]++;
i++;
}
for(i = 0; i<26 ;i++){
printf("%c: %d\n",i +'a',count[i]);
}
return 0;
}
请输入字符串(小写):aavv
a: 2
b: 0
c: 0
d: 0
e: 0
f: 0
g: 0
h: 0
i: 0
j: 0
k: 0
l: 0
m: 0
n: 0
o: 0
p: 0
q: 0
r: 0
s: 0
t: 0
u: 0
v: 2
w: 0
x: 0
y: 0
z: 0
一位叫约瑟夫的将军,战斗中,连同手下士兵一起被敌人俘虏了,手下的士兵宁死不投降,所以,约瑟夫将军想出了一个办法,让大家站成一个圈,从第一个人开始数数,谁数到7了,谁就自杀,自杀之后,他的下一个人重新从1开始数,遇到7,再自杀,直到最后只能剩下一个人。最后活下来的是约瑟夫,然后他不想死,他投降了。这种圈,在现今社会中被叫做,"约瑟夫环"。
要求,编写程序,命令行 输入 总人数(>=2) 及 数到几(>=2)自杀,
程序自动计算,将第 n 次 杀掉的 第m个人输出
最后再输出剩下的是几号。
例如:
输入 5人 数到3 自杀,
程序输出:
第 1 次自杀的人是 3 号;
第 2 次自杀的人是 1 号;
第 3 次自杀的人是 5 号;
第 4 次自杀的人是 2 号;
最后剩下的是 4 号。
方式1:如下图所示
#include
#include
typedef struct NODE{
int data;
struct NODE *next;
}node_t;
void create_node(node_t **pnew, int data){
*pnew = (node_t *)malloc(sizeof(node_t));
(*pnew)->data = data;
(*pnew)->next = NULL;
}
void insert_data_by_tail(node_t *phead, int data){
node_t *pnew = NULL;
create_node(&pnew, data);
//循环链表 插入第一个节点 和 其他节点方式不一样
if(phead->next == NULL){
phead->next = pnew;
pnew->next = phead->next;
}else{
node_t *ptemp = phead->next;
while(ptemp->next != phead->next){
ptemp = ptemp->next;
}
pnew->next = phead->next;
ptemp->next = pnew;
}
}
//约瑟夫处理
void deal_yuesefu(node_t *phead, int num){
node_t *plast = phead->next; //plast用来记录待删除节点的上一节点
node_t *pdel = NULL;
int i = 0;
int kill_num = 1;
node_t *pnew_one = phead->next; //pnew_one 用来记录每次数数的起点
//剩最后一个节点时 终止
while(pnew_one->next != pnew_one){
plast = pnew_one;
//数2被杀,plast 不用动,下一节点就是被杀的节点
//数3被杀,plast 移动一次,下一节点就是被杀的节点
//所以 i < num-1
for(i = 1; i < num-1; i++){
plast = plast->next;
}
pdel = plast->next; //定位要被杀的节点
printf("第 %d 次,杀掉 %d 号\n", kill_num, pdel->data);
pnew_one = pdel->next; //记录下一次开始数数的起点(被删除节点的下一个)
//删除要杀掉的节点
plast->next = pdel->next;
free(pdel);
kill_num++;
}
printf("剩下的是 %d 号\n", pnew_one->data);
phead->next = pnew_one;
}
void print_list(node_t *phead){
node_t *q = phead->next;
while(q->next != phead->next){
printf("%d ", q->data);
q = q->next;
}
printf("%d ", q->data);
printf("\n");
}
int main(int argc, const char *argv[])
{
if(3 != argc){
printf("Usage: %s <总人数> <数到几被杀>\n", argv[0]);
exit(-1);
}
int total = atoi(argv[1]);
int num = atoi(argv[2]);
//创建头节点
node_t *phead = NULL;
create_node(&phead, -1);
//插入数据
int i = 0;
for(i = 1; i <= total; i++){
insert_data_by_tail(phead, i);
}
//输出插入的数据
print_list(phead);
printf("----------------------------------------------\n");
//开始约瑟夫处理
deal_yuesefu(phead, num);
printf("----------------------------------------------\n");
//释放链表
//此时 只剩下唯一一个数据节点和头节点了
free(phead->next);
free(phead);
return 0;
}
方式2:如下图所示
#include
#include
typedef struct _Node{
int data;
struct _Node *next;
}node_t;
//创建头节点
int create_link(node_t **p, int in_data){
if(p == NULL){
printf("传参为NULL,请检查\n");
return -1;
}
*p = (node_t *)malloc(sizeof(node_t));
if(*p == NULL){
printf("内存分配失败\n");
return -1;
}
(*p)->data = in_data;
(*p)->next = NULL;
return 0;
}
//插入数据
int insert_data_by_tail(node_t *p,int sum){
if(p == NULL){
printf("传参为NULL,请检查\n");
return -1;
}
node_t *pnew = NULL;
create_link(&pnew,sum);
//循环链表 插入第一个节点 和 其他节点方式不一样
if(p->next == NULL){
p->next = pnew;
pnew->next = p;
}else{
node_t *ptemp = p;
while(ptemp->next != p){
ptemp = ptemp->next;
}
pnew->next = p;
ptemp->next = pnew;
}
return 0;
}
//约瑟夫处理
int delete(node_t *p, int sum,int k){
if(p == NULL){
printf("传参为NULL,请检查\n");
return -1;
}
node_t *ptemp = p;
node_t *pdel = NULL;
//遍历循环链表,删除操作
for(int i = 1; sum != 1; i++){
//找到删除节点的 前一节点
for(int j=0;jnext;
}
//删除操作
pdel = ptemp->next;
ptemp->next = pdel->next;
printf("第%d次杀的是%d号\n",i,pdel->data);
sum--;
ptemp = ptemp->next;
}
free(pdel);
pdel = NULL;
printf("最后剩下的是 %d 号\n",ptemp->data);
free(ptemp);
ptemp = NULL;
return 0;
}
//销毁链表
int destroy_list(node_t **p){
if(p == NULL || NULL == *p){
printf("传参为NULL,请检查\n");
return -1;
}
free(*p);
*p = NULL;
return 0;
}
int main(int argc, const char *argv[])
{
int sum = 0;
int k = 0;
NEXT:
printf("请输入人数:");
scanf("%d",&sum);
printf("数到几自杀:");
scanf("%d",&k);
if(sum < 2 && k <2){
printf("请输入总人数>=2及数到几(>=2)自杀");
goto NEXT;
}
//创建无头链表的 头节点,也就是第一个人
node_t *p = NULL;
create_link(&p, 1);
//插入数据
for(int i = 2; i <= sum; i++){
insert_data_by_tail(p,i);
}
delete(p, sum, k);
destroy_list(&p);
return 0;
}
请输入人数:5
数到几自杀:3
第1次杀的是3号
第2次杀的是1号
第3次杀的是5号
第4次杀的是2号
最后剩下的是 4 号