数据结构(四)

一、复习

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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式石油工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值