一、复习
1、单向链表
struct node
{
int data; //数据域
struct node *next; //指针域
};
2、双向循环链表
struct node
{
int data; //数据域
struct node *next; //指针域 指向当前节点的下一个节点
struct node *prior; //指向当前节点的前一个节点
};
二、队列
队列特点:先进先出(FIFO)
逻辑结构:线性结构
1、顺序队列
存储结构:顺序存储
相关结构体表示:
#define N 64
typedef int data_t;
typedef struct sequeue
{
data_t data[N];
int front; //队头 所有元素的出队从队头位置开始 指向第一个有效元素的下标
int rear; //队尾 所有元素的入队从最后一个元素的下一个元素位置开始 指向最后一个有效元素的下一个元素的下标
}Sequeue;
判空:front == rear
判满:rear == N-1
一般为了不造成资源空间的浪费,我们将顺序队列会升级为顺序循环队列
判空:front == rear
判满:(rear+1)%N == front
练习:完成顺序队列的创建、入队和出队
2、链式队列
存储结构:链式存储
链式队列的结构体定义
typedef int data_t;
typedef struct node
{
data_t data;
struct node *next;
}Node;
typedef struct linkqueue
{
struct node *front;
struct node *rear;
}Linkqueue;
作业:完成链式队列的入队和出队
预习:栈、树(二叉树的链式存储和遍历)、递归思想
linklist
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "linklist.h"
int main(int argc, char *argv[])
{
joseph(8, 1, 1);
/*
int n = 10;
Linklist *head = Linklist_Create();
while(n--)
{
Linklist_Insert_Head(head, n);
}
Linklist_Show(head);
Linklist_Insert_Pos(head, 0, 100);
Linklist_Show(head);
Linklist_Insert_Pos(head, 1, 99);
Linklist_Show(head);
Linklist_Delete_Pos(head, 0);
Linklist_Show(head);
Linklist_Delete_Pos(head, 7);
Linklist_Show(head);
Linklist_Reverse(head);
Linklist_Show(head);
*/
return 0;
}
/*===============================================
* 文件名称:linklist.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "linklist.h"
//创建链表
Linklist *Linklist_Create()
{
Linklist *head = (Linklist *)malloc(sizeof(Linklist)); //在堆区给当前节点开辟空间
if(NULL == head)
{
printf("malloc failed!\n");
return NULL;
}
//head->data = -1; //初始化data数值,在无头链表的头节点中该值不重要
head->next = NULL;
return head; //返回头节点的地址
}
//计算表长
int Linklist_Get_Length(Linklist *head)
{
int len = 0;
Linklist *p = head->next;
while(p != NULL)
{
len++;
p = p->next;
}
return len;
}
//判空
int Linklist_Is_Empty(Linklist *head)
{
if(head->next == NULL)
{
//printf("linklist is empty\n");
return 1;
}
else
{
return 0;
}
}
//头部插入
void Linklist_Insert_Head(Linklist *head, data_t data)
{
Linklist *new = (Linklist *)malloc(sizeof(Linklist)); //在堆区给当前节点开辟空间
if(NULL == new)
{
printf("malloc failed!\n");
return;
}
new->data = data;
new->next = NULL;
//插入操作
new->next = head->next;
head->next = new;
return;
}
//按位置插入
void Linklist_Insert_Pos(Linklist *head, int pos, data_t data)
{
Linklist *p = head; //将头节点赋值给指针p,用指针p完成遍历操作
int len = Linklist_Get_Length(head); //得到表长
if(pos < 0 || pos > len) //判断pos范围是否有效
{
printf("pos error!\n");
return;
}
Linklist *new = (Linklist *)malloc(sizeof(Linklist)); //在堆区给当前节点开辟空间
if(NULL == new)
{
printf("malloc failed!\n");
return;
}
new->data = data; //初始化新的节点
new->next = NULL;
for(int i = 0; i < pos; i++) //找到要插入节点的前一个节点地址
{
p = p->next;
}
new->next = p->next; //完成插入操作
p->next = new;
return;
}
//按位置删除
void Linklist_Delete_Pos(Linklist *head, int pos)
{
if(Linklist_Is_Empty(head) == 1)
{
printf("linklist is empty!\n");
return;
}
int len = Linklist_Get_Length(head);
if(pos < 0 || pos > len-1)
{
printf("pos error!\n");
return;
}
Linklist *p = head;
for(int i = 0; i < pos; i++) //找到要删除节点的前一个节点地址
{
p = p->next;
}
Linklist *q = p->next; //记录要删除节点的地址
p->next = q->next; //删除操作
free(q); //释放删除节点的地址空间
q = NULL;
return;
}
//打印表
void Linklist_Show(Linklist *head)
{
Linklist *p = head->next;
while(p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//逆序
void Linklist_Reverse(Linklist *head)
{
Linklist *p = head->next;
head->next = NULL;
Linklist *q = NULL;
while(p != NULL)
{
q = p->next;
p->next = head->next;
head->next = p;
p = q;
}
}
//joseph
void joseph(int n, int k, int m) //n代表元素个数 k表示从第几个元素开始 m代表数到几删除元素
{
Linklist *H = NULL;
Linklist *r = NULL;
Linklist *l = NULL;
for(int i = 1 ; i <= n; i++)
{
l = (Linklist *)malloc(sizeof(Linklist)); //创建新节点
l->data = i;
l->next = NULL;
if(H == NULL) //判断链表是否为空链表 如果H==NULL 说明一个元素都没有将H记为第一个有效元素 r记为最后一个有效元素
{
H = l;
r = l;
}
else //当链表存在有效元素时
{
r->next = l; //将新节点连接到最后一个有效元素后面
r = r->next; //将当前节点重新记为最后一个有效元素
}
}
r->next = H; //将最后一个有效元素连接到第一个节点,形成单向循环链表
r = H; //r表示起始地址
for(int i = 1; i < k; i++) //找到数数的起点
{
r = r->next;
}
while(r->next != r)
{
for(int i = 1; i < m-1; i++) //找到删除节点的前一个节点位置
{
r = r->next;
}
l = r->next; //l表示要删除的节点
r->next = l->next; //删除节点
printf("出列元素为:%d\n", l->data);
free(l);
r = r->next; //从删除节点的下一个节点开始 重新下一轮操作
}
printf("出列元素为:%d\n", r->data);
free(r);
r = NULL;
l = NULL;
H = NULL;
}
/*===============================================
* 文件名称:linklist.h
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef int data_t;
typedef struct node
{
data_t data; //数据域,用于存放数据
struct node *next; //指针域,用于存放下一个节点的地址
}Linklist;
//创建链表
Linklist *Linklist_Create();
//计算表长
int Linklist_Get_Length(Linklist *head);
//判空
int Linklist_Is_Empty(Linklist *head);
//头部插入
void Linklist_Insert_Head(Linklist *head, data_t data);
//按位置插入
void Linklist_Insert_Pos(Linklist *head, int pos, data_t data);
//按位置删除
void Linklist_Delete_Pos(Linklist *head, int pos);
//打印表
void Linklist_Show(Linklist *head);
//逆序
void Linklist_Reverse(Linklist *head);
void joseph(int n, int k, int m);
#endif
linkqueue
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "linklist.h"
int main(int argc, char *argv[])
{
int n = 10;
Linklist *head = Linklist_Create();
while(n--)
{
Linklist_Insert_Head(head, n);
}
Linklist_Show(head);
Linklist_Insert_Pos(head, 0, 100);
Linklist_Show(head);
Linklist_Insert_Pos(head, 1, 99);
Linklist_Show(head);
Linklist_Delete_Pos(head, 0);
Linklist_Show(head);
Linklist_Delete_Pos(head, 7);
Linklist_Show(head);
Linklist_Reverse(head);
Linklist_Show(head);
return 0;
}
/*===============================================
* 文件名称:linkqueue.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "linkqueue.h"
//创建链式队列
Linkqueue *Linkqueue_Create()
{
Node *head = (Node *)malloc(sizeof(Node));
if(NULL == head)
{
printf("head malloc filed!\n");
return NULL;
}
head->data = -1;
head->next = NULL;
Linkqueue *q = (Linkqueue *)malloc(sizeof(Linkqueue));
if(NULL == q)
{
printf("Linkqueue malloc failed!\n");
return NULL;
}
q->front = head;
q->rear = head;
return q;
}
/*===============================================
* 文件名称:linkqueue.h
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef int data_t;
typedef struct node //定义一个节点的结构体类型
{
data_t data; //数据域,用于存放数据
struct node *next; //指针域,用于存放下一个节点的地址
}Node;
typedef struct linkqueue //定义一个链式队列的结构体类型
{
struct node *front; //队头指针,指向第一个有效节点的前一个节点地址
struct node *rear; //队尾指针,指向最后一个节点的地址
}Linkqueue;
//创建链式队列
Linkqueue *Linkqueue_Create();
#endif
sequeue
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2024年03月21日
* 描 述:
================================================*/
#include "sequeue.h"
int main(int argc, char *argv[])
{
Sequeue *q = Sequeue_Create();
for(int i = 0; i < 48; i++)
{
Enqueue(q, i);
}
data_t data;
for(int i = 0; i < 48; i++)
{
Dequeue(q, &data);
printf("%d ", data);
}
printf("\n");
for(int i = 0; i < 3; i++)
{
Enqueue(q, i);
}
return 0;
}
/*===============================================
* 文件名称:sequeue.c
* 创 建 者:
* 创建日期:2024年03月21日
* 描 述:
================================================*/
#include "sequeue.h"
//创建顺序队列
Sequeue *Sequeue_Create()
{
Sequeue *q = (Sequeue *)malloc(sizeof(Sequeue));
if(NULL == q)
{
printf("malloc failed!\n");
return NULL;
}
q->front = 0;
q->rear = 0;
return q;
}
//入队
void Enqueue(Sequeue *q, data_t data)
{
if((q->rear+1)%N == q->front)
//if(q->rear == N-1)
{
printf("sequeue is full!\n");
return;
}
q->data[q->rear] = data;
q->rear = (q->rear+1)%N;
//q->rear++;
return;
}
//出队
void Dequeue(Sequeue *q, data_t *data)
{
if(q->front == q->rear)
{
printf("sequeue is empty!\n");
return;
}
*data = q->data[q->front];
q->front = (q->front+1)%N;
//q->front++;
return;
}
/*===============================================
* 文件名称:sequeue.h
* 创 建 者:
* 创建日期:2024年03月21日
* 描 述:
================================================*/
#ifndef __SEQLIST_H__
#define __SEQLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define N 50
typedef int data_t;
typedef struct sequeue
{
data_t data[N];
int front;
int rear;
}Sequeue;
//创建顺序队列
Sequeue *Sequeue_Create();
//入队
void Enqueue(Sequeue *q, data_t data);
//出队
void Dequeue(Sequeue *q, data_t *data);
#endif