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;
}
运行结果:
思维导图: