数据结构(三)
1、链表 – 单向链表
顺序表:
查找、修改效率高
插入和删除效率低
空间利用率低
链表:
插入和删除效率高
查找、修改效率低
空间利用率高
1、链表节点的相关表示:
typedef int data_t;
typedef struct node
{
data_t data;
struct node *next;
}Linklist;
有头链表:第一个节点的数据无效
无头链表:第一个节点的数据有效
2、单向循环链表
单向循环链表是在单向链表的基础上,将单向链表的最后一个有效节点的next指向第一个节点
3、双向循环链表
相关结构体定义:
typedef int data_t;
typedef struct node
{
data_t data; //数据域
struct node *next; //指向当前节点的下一个节点地址
struct node *prior; //指向当前节点的上一个节点地址
}Dlinklist;
作业:
1、完成单向链表的剩余功能(查找、修改、清空、销毁)
2、用单向循环链表完成约瑟夫环的输出(需要提交)
3、完成双向循环链表的剩余功能(删除、修改、查找、清空、销毁)
linklist
/*===============================================
* 文件名称: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;
}
/*===============================================
* 文件名称: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;
}
}
/*===============================================
* 文件名称: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);
#endif
clinklist
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "clinklist.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;
}
/*===============================================
* 文件名称:linklist.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "clinklist.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 = head;
return head; //返回头节点的地址
}
//计算表长
int Linklist_Get_Length(Linklist *head)
{
int len = 0;
Linklist *p = head->next;
while(p != head)
{
len++;
p = p->next;
}
return len;
}
//判空
int Linklist_Is_Empty(Linklist *head)
{
if(head->next == head)
{
//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 != head)
{
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 != head)
{
q = p->next;
p->next = head->next;
head->next = p;
p = q;
}
}
/*===============================================
* 文件名称: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);
#endif
dlinlist
/*===============================================
* 文件名称:main.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "dlinklist.h"
int main(int argc, char *argv[])
{
Dlinklist *head = Dlinklist_Create();
for(int i = 0; i < 10; i++)
{
Dlinklist_Insert_Pos(head, i, i);
}
Dlinklist_Show(head); //打印双向循环链表
return 0;
}
/*===============================================
* 文件名称:dlinklist.c
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#include "dlinklist.h"
//创建双向循环链表
Dlinklist *Dlinklist_Create()
{
Dlinklist *head = (Dlinklist *)malloc(sizeof(Dlinklist));
if(NULL == head)
{
printf("malloc failed!\n");
return NULL;
}
head->data = -1;
head->next = head;
head->prior = head;
return head;
}
void Dlinklist_Insert_Pos(Dlinklist *head, int pos, data_t data)
{
Dlinklist *new = (Dlinklist *)malloc(sizeof(Dlinklist));
if(NULL == new)
{
printf("malloc failed!\n");
return;
}
new->data = data;
new->next = NULL;
new->prior = NULL;
Dlinklist *p = head;
for(int i = 0; i < pos; i++)
{
p = p->next;
}
new->prior = p;
p->next->prior = new;
new->next = p->next;
p->next = new;
return;
}
//打印双向循环链表
void Dlinklist_Show(Dlinklist *head)
{
Dlinklist *p = head->next;
while(p != head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return;
}
/*===============================================
* 文件名称:dlinklist.h
* 创 建 者:
* 创建日期:2024年03月22日
* 描 述:
================================================*/
#ifndef __DLINKLIST_H__
#define __DLINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct node
{
data_t data;
struct node *next; //指向下一个节点的地址
struct node *prior; //指向上一个节点的地址
}Dlinklist;
Dlinklist *Dlinklist_Create(); //创建双向循环链表
void Dlinklist_Show(Dlinklist *head); //打印双向循环链表
void Dlinklist_Insert_Pos(Dlinklist *head, int pos, data_t); //按位置插入
#endif