dataStructureDay060808

目录

今日作业:

1、使用单向循环链表完成约瑟夫环问题

 头文件:looplink.h

源文件:looplink.c:

测试:main.c:

结果

​编辑2、使用栈的操作完成进制转换问题,例如输入一个十进制数据,程序输出该数据的二进制数

 头文件:stack.h:

源文件:stack.c

测试:main.c:

结果:

思维导图

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;
}
结果

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;
}
结果:

思维导图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值