目录
编辑2、使用栈的操作完成进制转换问题,例如输入一个十进制数据,程序输出该数据的二进制数
1、使用单向循环链表完成约瑟夫环问题
头文件:looplink.h
#ifndef __LOOPLINK_H__
#define __LOOPLINK_H__
typedef int datatype;
//定义节点结构体类型
typedef struct Node
{
union
{
datatype data;//普通指针数据域
int len;//头节点数据域
};
struct Node *next; //指针域
}Node, *LoopLink;
//创建循环链表
LoopLink list_create();
//尾插
int list_insert_tail(LoopLink L,datatype e);
//判空
int list_empty(LoopLink L);
//遍历
void list_show(LoopLink L);
//尾删
int list_delete_tail(LoopLink L);
//销毁
void list_free(LoopLink L);
//约瑟夫环
void joseph_cycle(LoopLink L,int n);
#endif
源文件:looplink.c:
#include"looplink.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//创建循环链表
LoopLink list_create(){
//堆区申请一个头结点
LoopLink L = (LoopLink)malloc(sizeof(Node));
if(NULL==L){
printf("创建失败\n");
return NULL;
}
//初始化
L->len = 0;
L->next = L; //指针域指向自己
printf("创建成功\n");
return L;
}
//尾插
int list_insert_tail(LoopLink L,datatype e){
if(NULL == L){
printf("链表不合法\n");
return -1;
}
//申请节点封装数据
LoopLink p = (LoopLink)malloc(sizeof(Node));
if(NULL==p){
printf("节点申请失败\n");
return 0;
}
//将数据封装到节点中
p->data = e;
p->next = NULL;
//遍历找到最后一个节点
LoopLink q = L;
//最后一个节点特点:后继节点为头结点
while(q->next != L){
q = q->next;
}
//尾插操作
p->next = L; //p->next = q->next
q->next = p;
//表长变化
L->len++;
printf("插入成功\n");
return 1;
}
//判空
int list_empty(LoopLink L){
if(NULL != L){
return L->next == L;
}
printf("链表不合法\n");
return -1; //链表不合法
}
//遍历
void list_show(LoopLink L){
if(NULL==L|| list_empty(L)){
printf("遍历失败\n");
return;
}
//定义遍历指针,从第一个节点出发
LoopLink q = L->next;
while(q!=L){
printf("%d\t",q->data);
q = q->next;
}
putchar(10);
}
//尾删
int list_delete_tail(LoopLink L){
if(NULL==L|| list_empty(L)){
printf("删除失败\n");
return 0;
}
//遍历链表找到倒数第二个节点
LoopLink q = L->next;
while(L!=q->next->next){
q=q->next;
}
//尾删操作
free(q->next); //将最后一个节点释放
q->next = L; // 将倒数第二个节点的指针域指向头结点
//表长变化
L->len--;
}
//销毁
void list_free(LoopLink L){
if(NULL==L){
printf("销毁失败\n");
return ;
}
//如果不为空。就将所有节点释放
while(!list_empty(L)){
list_delete_tail(L);
}
//将头结点释放
free(L);
L=NULL;
printf("释放成功\n");
return;
}
//约瑟夫环
void joseph_cycle(LoopLink L,int n){
if(NULL == L){}
LoopLink q = L->next;
LoopLink tmp = NULL;
while(L->next!=L){
for(int i=0; i<n; i++){
q = q->next;//q按顺序走n次,如果是头节点L,就多走一次
if(q == L){
q = q->next;
}
}
printf("%d\t",q->data);
if(q->next==L){ //如果q的下一个是L,就是尾删.
list_delete_tail(L);
q = L->next;//尾删之后,q理应指向下一个,而q本身就是最后一个,应该指向
}else{
q->data = q->next->data;//要删除q,把q下一个节点的数据给q,原来的q就相当于没了,变成了下一个节点,然后删除下一个节点即可
tmp = q->next;//保存一下q下一个节点的位置
q->next = tmp->next;//q指向下下个节点
free(tmp);//释放q的下一个节点
tmp = NULL;
}
}
putchar(10);
}
测试:main.c:
#include"looplink.h"
#include<stdio.h>
int main(int argc, const char *argv[])
{
//创建一个循环链表
LoopLink L = list_create();
if(NULL == L){
return -1;
}
//定义一个变量m,决定要对一个多大的循环链表进行操作
int m = 0;
printf("请输入约瑟夫环元素的个数:");
scanf("%d",&m);
for(int i=1; i<=m; i++){
list_insert_tail(L,i);
}
printf("请输入每间隔多少元素取出:");
int n = 0;
scanf("%d",&n);
joseph_cycle(L,n);
return 0;
}
结果
![](https://i-blog.csdnimg.cn/blog_migrate/e8f4b23433069e011d9a7e7517d2bc86.png)
2、使用栈的操作完成进制转换问题,例如输入一个十进制数据,程序输出该数据的二进制数
头文件:stack.h:
#ifndef __STACK_H__
#define __STACK_H__
#define MAX 8
typedef int datatype;
typedef struct
{
datatype *data;//指向堆区空间,用于存储栈的容器
int top;//记录栈顶元素的下标
}Stack, *StackPtr;
//创建栈
StackPtr stack_create();
//判空
int stack_empty(StackPtr S);
//判满
int stack_full(StackPtr S);
//入栈
int stack_push(StackPtr S,datatype e);
//遍历栈
void stack_show(StackPtr S);
//出栈
int stack_pop(StackPtr S);
//获取栈顶元素
datatype * stack_top(StackPtr S);
//求栈的大小
int stack_size(StackPtr S);
//销毁栈
void stack_free(StackPtr S);
#endif
源文件:stack.c
#include"stack.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//创建栈
StackPtr stack_create(){
//在堆区申请一个顺序栈的大小
StackPtr S = (StackPtr)malloc(sizeof(Stack));
if(NULL == S){
printf("栈申请失败\n");
return NULL;
}
//给栈中的连续空间申请内容
S->data = (datatype *)malloc(sizeof(datatype)*MAX);
if(NULL==S->data){
printf("申请失败\n");
free(S);//数组空间申请失败,整个栈就没意义了,要释放
//防止内存泄露
return NULL;
}
//初始化
S->top = -1; //表明现在是一个空栈
printf("创建成功\n");
return S;
}
//判空 空返回真。非空返回假
int stack_empty(StackPtr S){
//判断逻辑
if(NULL != S){
return S->top == -1;
}
printf("所给链表不合法\n");
return -1;
}
//判满 满返回真,非满返回假
int stack_full(StackPtr S){
//判断逻辑
if(NULL != S){
return S->top == MAX-1;
}
printf("所给链表不合法\n");
return 0;
}
//入栈,进展,压栈,先加后压
int stack_push(StackPtr S,datatype e){
//判断逻辑
if(NULL==S|| stack_full(S)){
printf("入栈失败\n");
return 0;
}
//先加后压
S->top++;
S->data[S->top] = e;//将数据存放到栈中
printf("入栈成功\n");
return 1;
}
//遍历栈
void stack_show(StackPtr S){
//判断逻辑
if(NULL==S|| stack_empty(S)){
printf("遍历失败\n");
return ;
}
//开始遍历
printf("从栈顶到栈底元素分别是:");
for(int i=S->top; i>=0; i--){
printf("%d\t",S->data[i]);
}
putchar(10);
}
//出栈
int stack_pop(StackPtr S){
//判断逻辑
if(NULL==S ||stack_empty(S)){
printf("出栈失败\n");
return 0;
}
//出栈逻辑,先弹后减
// datatype e = S->data[S->top];
printf("%d\t",S->data[S->top]);//e
S->top--;
return 1;
}
//获取栈顶元素
datatype * stack_top(StackPtr S){
if(NULL==S|| stack_empty(S)){
printf("获取失败\n");
return NULL;
}
//可以获取,将栈顶元素的地址返回
return &S->data[S->top];
}
//求栈的大小
int stack_size(StackPtr S){
if(NULL!=S){
return S->top+1;
}
printf("所给链表不合法\n");
return 1;
}
//销毁栈
void stack_free(StackPtr S){
if(NULL==S){
printf("释放失败\n");
return;
}
//将动态数组空间释放
free(S->data);
S->data = NULL;
//将整个栈释放
free(S);
S=NULL;
printf("释放成功\n");
return;
}
测试:main.c:
#include"stack.h"
#include<stdio.h>
int main(int argc, const char *argv[])
{
//创建一个顺序栈
StackPtr S = stack_create();
if(NULL==S){
return -1;
}
int num = 0;
printf("请输入一个十进制数:");
scanf("%d",&num);
while(num/2){
stack_push(S,num%2);
num =num/ 2;
}
stack_push(S,num);
while(-1!=S->top){
stack_pop(S);
}
//调用销毁栈函数
stack_free(S);
return 0;
}