双向链表、循环链表和顺序栈

1> 将双向链表和循环链表自己实现一遍,至少要实现创建、增、删、改、查、销毁工作

双向链表:

代码

doublelinklist.h:

#ifndef DOUBLELINKLIST_H
#define DOUBLELINKLIST_H
#include<myhead.h>

#define MAX 100

typedef char datatype;   //数据域的类型

typedef struct Node
{
    union 
    {
      int len;            //头结点数据域
      datatype data;       //普通节点数据域      
    };
    struct Node * prio;            //指向前驱节点的指针
    struct Node * next;            //指向后继节点的指针
}Node, *NodePtr;


//创建链表
NodePtr list_create();

//链表判空
int list_empty(NodePtr L);

//申请节点封装数据
NodePtr apply_node(datatype e);

//链表头插
int list_insert_head(NodePtr L, datatype e);

//链表遍历
int list_show(NodePtr L);

//按位置查找返回节点
NodePtr list_search_pos(NodePtr L, int pos);

//链表任意位置删除
int list_delete_pos(NodePtr L, int pos);

//链表删除
void list_destroy(NodePtr L);

//按位置修改
int list_update_pos(NodePtr L, int pos, datatype e);

#endif

doublelinklist.c:

#include "doublelinklist.h"

//创建链表
NodePtr list_create()
{
	//在堆区申请一个头结点
	NodePtr L = (NodePtr)malloc(sizeof(Node));
	if(NULL == L)   //if(L = NULL)
	{
		printf("创建失败\n");
		return NULL;
	}
 
	//说明链表创建成功
	L->len = 0;           //链表长度为0
	L->prio = NULL;       //前驱指针为空
	L->next = NULL;        //后继指针为空
	
	printf("创建成功\n");
	return L;
}

//链表判空
int list_empty(NodePtr L)
{
	return L->next == NULL;
}

//申请节点封装数据
NodePtr apply_node(datatype e)
{
	//申请节点空间的大小
	NodePtr p = (NodePtr)malloc(sizeof(Node));
	if(NULL == p)
	{
		printf("节点申请失败\n");
		return NULL;
	}

	//给节点赋值
	p->data = e;
	p->prio = NULL;
	p->next = NULL;

	return p;
}

//链表头插
int list_insert_head(NodePtr L, datatype e)
{
	//判断逻辑
	if(NULL == L)
	{
		printf("插入失败\n");
		return -1;
	}

	//申请节点封装数据
	NodePtr p = apply_node(e);
	if(NULL==p)
	{
		return -1;
	}

	//头插逻辑
	if(list_empty(L))
	{   //链表为空时的插入逻辑
		p->prio = L;
		L->next = p;
	}else
	{
		//链表非空时的插入
		p->prio = L;
		p->next = L->next;
		L->next->prio = p;  //p->next->prio=p;
		L->next = p;
	}

	printf("插入成功\n");

	L->len++;     //链表长度变化

	return 0;
}

//链表遍历
int list_show(NodePtr L)
{
	//判断逻辑
	if(NULL==L || list_empty(L))
	{
		printf("遍历失败\n");
		return -1;
	}
 
	//遍历逻辑
	NodePtr q = L->next;  //从第一个节点出发
	while(q)
	{
		//输出数据域
		printf("%c\t", q->data);
 
		//遍历指针后移
		q = q->next;
	}
	printf("\n");
 
}

//按位置查找返回节点
NodePtr list_search_pos(NodePtr L, int pos)
{
	//判断逻辑
	if(NULL==L || list_empty(L)||pos<0 || pos>L->len)
	{
		printf("查找失败\n");
		return NULL;
	}

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

	//返回节点
	return q;

}

//链表任意位置删除
int list_delete_pos(NodePtr L, int pos)
{
	//判断逻辑
	if(NULL==L || list_empty(L) || pos<1 || pos>L->len)
	{
		printf("删除失败\n");
		return -1;
	}
	
	//找到要删除的节点
	NodePtr q = list_search_pos(L, pos);
	
	//删除逻辑
	if(q->next == NULL)
	{
		//表示q为最后一个节点

		q->prio->next = NULL;
 
	}else
	{
		//上传下达
		q->prio->next = q->next;
		q->next->prio = q->prio;
	}
 
	free(q);    //释放自己
	q = NULL;
 
 
	printf("删除成功\n");
	//表长变化
	L->len--;
 
	return 0;
 
}

//按位置修改
int list_update_pos(NodePtr L, int pos, datatype e)
{
	if(NULL==L || list_empty(L) || pos<1 || pos>L->len)
	{
		printf("修改失败\n");
		return -1;
	}

	//找到要修改的结点
	NodePtr q = list_search_pos(L,pos);

	//修改结点
	q->data = e;
	printf("修改成功\n");

	return 0;
}

//链表删除
void list_destroy(NodePtr L)
{
	//判断逻辑
	if(NULL==L)
	{
		printf("删除失败\n");
		return;
	}

	//删除所有节点
	while(!list_empty(L))
	{
		list_delete_pos(L, 1);
	}


	//删除头结点
	free(L);
	L = NULL;

	printf("链表释放成功\n");

}

main.c:

#include "doublelinklist.h"

int main(int argc, const char *argv[])
{
	//调用创建函数
	NodePtr L = list_create();
	if(NULL == L)
	{
		return -1;
	}
 
	//调用头插函数
	list_insert_head(L, 'Q');
	list_insert_head(L, 'W');
	list_insert_head(L, 'E');
	list_insert_head(L, 'R');
	list_insert_head(L, 'D');
	list_insert_head(L, 'F');
 
	//调用遍历函数
	list_show(L);
 
	//调用任意位置删除函数
	list_delete_pos(L, 1);
	list_delete_pos(L, 3);
	list_delete_pos(L, L->len);
 
	list_show(L);

	//调用按位置修改函数
	list_update_pos(L,2,'S');

	list_show(L);
 
	//释放链表
	list_destroy(L);
	L = NULL;
 
	list_show(L);

	return 0;
}

运行结果:

循环链表:

代码

looplinklist.h:

#ifndef LOOPLINKLIST_H
#define LOOPLINKLIST_H

#include<myhead.h>

//定义数据类型
typedef int datatype;
 
//定义结点类型
typedef struct Node
{
	union
	{
		int len;    //头结点数据域
		datatype data;  //普通结点数据域
	};
 
	struct Node *next;   //指针域
}Node, *NodePtr;

//创建循环链表
NodePtr list_create();

//链表申请空间封装节点
NodePtr apply_node(datatype e);

//按位置进行查找
NodePtr list_search_pos(NodePtr L, int pos);

//链表尾插
int list_insert_tail(NodePtr L, datatype e);

//链表遍历
int list_show(NodePtr L);

//链表的头删
int list_delete_head(NodePtr L);

//链表销毁
void list_destroy(NodePtr L);

//按位置修改
int list_update_pos(NodePtr L, int pos, datatype e);


#endif

 looplinklist.c:

#include "looplinklist.h"

//创建循环链表
NodePtr list_create()
{
	//在堆区申请一个头结点
	NodePtr L = (NodePtr)malloc(sizeof(Node));
	if(NULL == L)
	{
		printf("创建失败\n");
		return NULL;
	}

	//初始化
	L->len = 0;
	L->next = L;       //头结点指针域指向自己

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

//链表判空
int list_empty(NodePtr L)
{
	return L->next == L;
}

//链表申请空间封装节点
NodePtr apply_node(datatype e)
{
	//堆区申请一个节点的空间
	NodePtr p = (NodePtr)malloc(sizeof(Node));
	if(NULL == p)
	{
		printf("申请失败\n");
		return NULL;
	}
 
	//给节点赋值
	p->data = e;
	p->next = NULL;
 
	return p;
}

//按位置进行查找
NodePtr list_search_pos(NodePtr L, int pos)
{
	//判断逻辑
	if(NULL==L || pos<0 || pos>L->len)
	{
		printf("查找失败\n");
		return NULL;
	}
 
	//查找逻辑
	NodePtr q = L;

	for(int i=0; i<pos; i++)
	{
		q = q->next;
	}
 
	return q;
}

//链表尾插
int list_insert_tail(NodePtr L, datatype e)
{
	//判断逻辑
	if(NULL == L)
	{
		printf("插入失败\n");
		return -1;
	}

	//找到最后一个节点
	NodePtr q = list_search_pos(L, L->len);

	//封装节点
	NodePtr p = apply_node(e);
	if(NULL == p)
	{
		return -1;
	}

	//插入逻辑
	p->next = q->next;
	q->next = p;

	//表的变化
	L->len++;
	printf("插入成功\n");
	return 0;

}

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

	//遍历逻辑
	NodePtr q = L->next;
	while(q != L)
	{
		printf("%c\t", q->data);
		q = q->next;        //继续访问下一个
	}
	printf("\n");

}

//链表的头删
int list_delete_head(NodePtr L)
{
	//判断逻辑
	if(NULL==L || list_empty(L))
	{
		printf("删除失败\n");
		return -1;
	}

	//头删逻辑
	NodePtr p = L->next;    //标记
	L->next = p->next;      //孤立
	free(p);                //删除
	p = NULL;


	//表长变化
	L->len--;
	printf("删除成功\n");
	return 0;
}

//按位置修改
int list_update_pos(NodePtr L, int pos, datatype e)
{
	//判断逻辑
	if(NULL==L || list_empty(L))
	{
		printf("修改失败\n");
		return -1;
	}

	//找到结点
	NodePtr p = list_search_pos(L,pos);
	
	//修改结点
	p->data = e;

	printf("修改成功\n");

	return 0;
}

//链表销毁
void list_destroy(NodePtr L)
{
	//判断逻辑
	if(NULL == L)
	{
		printf("释放失败\n");
		return ;
	}

	//删除节点
	while(!list_empty(L))
	{
		list_delete_head(L);
	}

	//释放头结点
	free(L);
	L = NULL;
	printf("销毁成功\n");
}

main.c:

#include "looplinklist.h"


int main(int argc, const char *argv[])
{
	NodePtr L = list_create();
	if(L == NULL)
	{
		return -1;
	}

	list_insert_tail(L,'d');
	list_insert_tail(L,'r');
	list_insert_tail(L,'q');
	list_insert_tail(L,'x');
	list_show(L);

	list_delete_head(L);
	list_show(L);

	list_update_pos(L,2,'p');
	list_show(L);

	

	list_destroy(L);
	L = NULL;
	list_show(L);
	
	return 0;
}

运行结果:

2> 使用循环链表完成约瑟夫环问题

代码:

#include<myhead.h>

//结点类型
typedef struct Node 
{
	union
	{
		int len;             //头结点数据域
   		int number;          //普通结点数据域
	};
    struct Node *next;     //指针域
} Node,*NodePtr;

//创建循环链表
NodePtr create() 
{
	//申请头结点
    NodePtr L = (NodePtr)malloc(sizeof(Node));
	if(L==NULL)
	{
		printf("创建失败!\n");
		return NULL;
	}

	//初始化
    L->len = 0;
    L->next = L;

    return L;
}

//链表申请空间封装节点
NodePtr apply(int e)
{
	//堆区申请一个节点的空间
	NodePtr p = (NodePtr)malloc(sizeof(Node));
	if(NULL == p)
	{
		printf("申请失败\n");
		return NULL;
	}
 
	//给节点赋值
	p->number = e;
	p->next = NULL;
 
	return p;
}

//解决约瑟夫问题
void solveJosephusProblem(int n, int k) 
{
	if(n>2)
	{
	    //创建循环链表
	    NodePtr L = create();
	    NodePtr current = L;
	    NodePtr prev = NULL;
	
	    for (int i = 2; i <= n; i++) 
		{
	        NodePtr newL = apply(i);
	        current->next = newL;
	        prev = current;
	        current = newL;
	    }
	    current->next = L; // 形成循环

	    NodePtr ptr1 = L;
	    NodePtr ptr2 = NULL;

	    // 约瑟夫环算法
	    while (ptr1->next != ptr1) {
	        for (int i = 1; i < k; i++) {
	            ptr2 = ptr1;
	            ptr1 = ptr1->next;
	        }
	        printf("删除节点:%d\n", ptr1->number);
	        ptr2->next = ptr1->next;
	        free(ptr1);
	        ptr1 = ptr2->next;
	    }
	
	    printf("最后剩下的节点是:%d\n", ptr1->number);
	    free(ptr1);
	}

	if(n<1)
	{
		printf("结点不足1,输入错误\n");
	}
	if(n==1)
	{
		printf("只有一个结点\n");
	}
	if(n==2)
	{
		if(k%2==0)
			printf("最后剩下的节点是:1\n");
		else
			printf("最后剩下的节点是:2\n");
	}
}

int main() 
{
    int n, k;
    printf("请输入总人数:");
    scanf("%d", &n);
	printf("请输入报数值:");
    scanf("%d", &k);

	//调用解决约瑟夫问题函数
    solveJosephusProblem(n, k);
    
	return 0;
}

运行结果:

3>使用栈,完成进制转换

输入:一个整数,进制数

输出:该数的对应的进制数

代码:

#include<myhead.h>

typedef int datatype;   //数据类型

#define MAX 16           //顺序栈最大容量

//定义顺序栈的类型
typedef struct 
{
	datatype *data;      //存储栈的容器,指向堆区空间
	int top;             //记录栈顶元素的下标
}Stack, *StackPtr;

//创建栈
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");
		return NULL;
	}
	//给空间内容初始化
	//memset(S->data, 0, sizeof(datatype)*MAX);
	bzero(S->data, 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 e)
{
	//判断逻辑
	if(NULL==S || stack_full(S))
	{
		printf("入栈失败\n");
		return ;
	}

	//入栈逻辑
	S->top++;            //偏移栈顶位置
	S->data[S->top] = e;  //将数据压入栈中

}

//出栈
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 ;
	}

	printf("转换后的数为:");
	for(int i=S->top; i>=0; i--)
	{
		int t = S->data[i];
		if(t<10)
		{
			printf("%d", t);
		}else
		{
			printf("%c",t - 10 + 'A');
		}
	}

	printf("\n");
}

//获取栈顶元素
datatype* stack_get_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)
	{
		printf("操作失败\n");
		return -1;
	}

	//返回大小
	return S->top+1;
}


//销毁栈
void stack_destroy(StackPtr S)
{
	if(S != NULL)
	{
		//销毁栈的容器
		free(S->data);
		S->data = NULL;

		//销毁栈
		free(S);
		S = NULL;
	}
}

int main(int argc, const char *argv[])
{
	int n = 0, m = 0;
	printf("请输入一个整数:");
	scanf("%d",&n);
	printf("请输入转换后为几进制:");
	scanf("%d",&m);

	//创建一个栈
	StackPtr S = stack_create();

	//存储转换后的数
	while(n)
	{
		stack_push(S,n%m);
		n /= m;
	}

	//展示转换后的数
	stack_show(S);

	//销毁栈
	stack_destroy(S);
	S = NULL;
	
	return 0;
}

运行结果:

思维导图:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值