数据结构day5

一、思维导图

二、课后练习


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

//头文件

#ifndef JOSEPH_RING_H
#define JOSEPH_RING_H

#include <myhead.h>

typedef char datatype;

//定义单向循环链表结点
typedef struct Node
{
	datatype data;
	struct Node *next;
}Node,*NodePtr;

//创建单向循环链表
NodePtr list_create(datatype element);

//链表的判空
int list_empty(NodePtr H);

//链表结点的封装
NodePtr list_apply_node(datatype element);

//链表的尾插
int list_insert(NodePtr H,datatype element);

//链表的遍历
int list_show(NodePtr H);

//通过位置查找
NodePtr list_search_pos(NodePtr H,int pos);

//无头结点单向循环链表的头删
void deleteHead(NodePtr head);

//任意位置删除元素
int list_delete_pos(NodePtr H,int pos);


#endif

//功能函数

#include "Joseph_Ring.h"

//创建单向循环链表
NodePtr list_create(datatype element)
{
	//在堆区申请头指针
	NodePtr H = (NodePtr)malloc(sizeof(Node));
	if(NULL == H)
	{
		printf("创建失败\n");
		return NULL;
	}

	//初始化
	H->next = H; 		//头结点指针域指向自己
	H->data = element;

	printf("创建成功\n");
	return H;
}


//链表的判空
int list_empty(NodePtr H)
{
	return H == NULL;
}


//链表结点的封装
NodePtr list_apply_node(datatype element)
{
	//堆区申请结点
	NodePtr p = (NodePtr)malloc(sizeof(Node));
	if(NULL == p)
	{
		printf("申请失败\n");
		return NULL;
	}

	//给结点赋值
	p->data = element;
	p->next = NULL;

	return p;
}

//链表的尾插
int list_insert(NodePtr H,datatype element)
{
	//判断逻辑
	if(NULL == H)
	{
		printf("尾插失败\n");
		return -1;
	}

	//申请结点
	NodePtr p = list_apply_node(element);
	if(NULL == p)
	{
		return -1;
	}
	//查找原链表尾结点
	NodePtr q = H;

	while(q->next != H)
	{
		q = q->next;
	}

	p->next = q->next;
	q->next = p;

	printf("插入成功\n");
	return 0;
}

//链表的遍历
int list_show(NodePtr H)
{
	//判断逻辑
	if(NULL ==H)
	{
		printf("遍历失败\n");
		return -1;
	}

	//遍历链表
	NodePtr p = H; 		//定义遍历指针

	do	{
		printf("%c\t",p->data);
		p = p->next;

	}
	while(p!=H);
	printf("\n");
	return 0;
}

//链通过位置表查找
NodePtr list_search_pos(NodePtr H,int pos)
{
	//判断逻辑
	if(NULL == H)
	{
		printf("查找失败\n");
		return NULL;
	}

	//查找逻辑
	//遍历指针从头结点出发
	NodePtr q = H;
	for(int i =1;i<pos;i++)
	{
		q = q->next;
	}

	return q; 		//将找到的结点地址返回
}

//无头结点单向循环链表的头删
void deleteHead(NodePtr H)
{
	//判断逻辑
	if(NULL == H)
	{
		printf("头删错误\n");
		return;
	}

	//定义指针遍历到结尾
	NodePtr tail = H;
	while(tail->next !=H)
	{
		tail = tail->next;
	}

	//删除头结点
	NodePtr temp = H;
	tail->next = H->next; //尾结点指向头结点的下一个结点
	H = H->next; 		//头指针指向下一个结点
	//释放原来的头结点
	free(temp);
	temp = NULL;
	
}

//单向链表任意位置删除
int list_delete_pos(NodePtr H,int pos)
{
    //判断逻辑
	if(NULL == H || pos<1)
	{
		printf("删除失败\n");
		return -1;
	}

	//头结点删除
	 if(pos == 1)
	 {
		deleteHead(H);
	 }
	 else
	 {
		 //找删除位置的前驱结点
		 NodePtr q = list_search_pos(H,pos-1);

		 //删除三部曲
		 NodePtr p = q->next; 		//标记
		 q->next = p->next; 			//断连
		 free(p); 					//释放
		 p = NULL; 

		 printf("任意位置删除成功\n");
	 }
	return 0;
}


//主函数

#include "Joseph_Ring.h"
int main(int argc, const char *argv[])
{
	//设置
	int num,mode,start;
	printf("请输入总元素个数:");
	scanf("%d",&num);

	printf("请输入规则个数:");
	scanf("%d",&mode);

	printf("请输入开始位置:");
	scanf("%d",&start);

	getchar();
	//输入第一个元素创建链表
	datatype element;
	printf("请输入首个元素:");
	scanf("%c",&element);
	getchar();
	//创建头结点
	NodePtr H = list_create(element);
	//判断逻辑
	if(NULL == H )
	{
		printf("error\n");
	}
	//循环插入元素
	for(int i=0;i<num-1;i++)
	{
		datatype e;
		printf("请输入元素:");
		scanf("%c",&e);
		getchar();
		list_insert(H,e);
	}

	//展示原始顺序
	list_show(H);

	//按规则删除结点
	//从start开始,每间隔mode个元素删除
	//每轮删除将头结点指向下一轮的起始结点
	//遍历到第start个结点s
	NodePtr s = H;
	for(int i=1;i<start;i++)
	{
		s = s->next;
	}

	printf("原始头结点:%c\n",H->data);
	printf("规定起点:%c\n",s->data);

	while(s->next != s)
	{	
		//从第s个结点开始,遍历mode个结点,并删除第mode个结点
		NodePtr m = s;
		for(int i=1;i<mode;i++)
		{
			//记录m的
			m = m->next;
		}

		//删除结点m
 		printf("删除:%c\n",m->data);
		//将s指向m的下一个结点
		//将m结点删除
		NodePtr	p = m->next;
		//释放第m个
		list_delete_pos(s,mode);

		//s指向释放结点的下一个结点
		s  = p;	

		list_show(s);
	}
	return 0;
}

普通测试

头删测试

2、使用栈,完成进制转换(输入:一个整数,进制数,输出:该数的对应的进制数)

//头文件

#ifndef DEC_TO_BIN_H
#define DEC_TO_BIN_H

#include <myhead.h>

typedef int datatype;
#define MAX 100

typedef struct
{
	datatype *data;
	int top;
}Stack,*StackPtr;

//创建栈
StackPtr stack_create();

//判空
int stack_empty(StackPtr S);

//判满
int stack_full(StackPtr S);

//入栈
void stack_push(StackPtr S,datatype element);

//出栈
void stack_pop(StackPtr S);

//遍历栈
void stack_show(StackPtr S);

//将整数转换成对应的进制数
void Dec_to_Bin(StackPtr S, int element,int num);



#endif

//功能函数

#include "Dec_to_Bin.h"

//创建栈
StackPtr stack_create()
{
	//在堆区申请一个栈大小的空间
	StackPtr S = (StackPtr)malloc(sizeof(Stack));
	if(NULL == S)
	{
		printf("创建失败\n");
		return NULL;
	}

	//栈申请成功,申请存储栈的空间
	//申请MAX个datatype类型数据大小的空间
	S->data = (datatype *)malloc(sizeof(datatype) * MAX);
	if(NULL == S->data)
	{
		printf("申请栈存储空间失败\n");
		return NULL;
	}

	//给空间内容初始化
	memset(S->data,0,sizeof(datatype)*MAX);

	//栈顶元素变量初始化
	S->top = -1;
	//返回栈地址
	return S;
}

//判空
int stack_empty(StackPtr S)
{
	return S->top == -1;
}
//判满
int stack_full(StackPtr S)
{
	return S->top == MAX-1;

}
//入栈
void stack_push(StackPtr S,datatype element)
{
	//判断逻辑
	if(NULL == S || stack_full(S))
	{
		printf("入栈失败\n");
		return;
	}

	//入栈
	//先偏移栈顶位置
	S->top++;
	//再将数据压入栈中
	S->data[S->top] = element;
}
//出栈
void stack_pop(StackPtr S)
{
	//判断逻辑
	if(NULL == S || stack_empty(S))
	{
		printf("出栈失败\n");
		return;
	}

	//出栈
	//先弹后减
	printf("%d出栈成功\n",S->data[S->top]);
	S->top--;
}

//遍历栈
void stack_show(StackPtr S)
{
	//判断逻辑
	if(NULL == S ||stack_empty(S))
	{
		printf("遍历失败\n");
		return;
	}

	for(int i=S->top;i>=0;i--)
	{
		printf("%d",S->data[i]);
	}
	printf("\n");
}


//将整数转换成对应的进制数
void Dec_to_Bin(StackPtr S, int element,int num)
{
	//对element循环取余并压入栈中
	while(element)
	{
		stack_push(S,element%num);
		//将element除以num
		element /= num;
	}
}

//主函数

	while(1)
	{
		//创建栈
		StackPtr S = stack_create();

		//提示输入
		int element,num;
		printf("请输入一个整数和你需要转换的进制数:");
		scanf("%d%d",&element,&num);

		//将整数转换成进制数存入栈中
		Dec_to_Bin(S,element,num);

		//循环出栈
		printf("该整数的%d进制数为:",num);
		while(S->top >0)
		{
			stack_pop(S);

		}
		printf("\n");
	}

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值