一、双向循环链表
#include "head.h"
//创建结点
cir_dou_list_p create_node(int flag,int element)
{
cir_dou_list_p node=(cir_dou_list_p)malloc(sizeof(cir_dou_list));
if(node==NULL)
{
printf("空间申请失败..\n");
return NULL;
}
if(flag==1)
{
node->len=0;
}
else if(flag==0)
{
node->data=element;
}
else
{
printf("输入的flag不合理..\n");
}
node->next=node;
node->prev=node;
return node;
}
//头插
void insert_head(cir_dou_list_p head,int element)
{
if(head==NULL)
{
printf("入参为空..\n");
return;
}
cir_dou_list_p a=create_node(0,element);
a->next=head->next;
a->prev=head;
head->next=a;
if(a->next!=head)
{
a->next->prev=a;
}
head->len++;
}
//判空
int empty(cir_dou_list_p head)
{
if(head==NULL)
{
printf("入参为空..\n");
return -1;
}
if(head->next==head)
{
printf("双向链表为空..\n");
return -2;
}
return 0;
}
//尾插
void insert_rear(cir_dou_list_p head,int element)
{
cir_dou_list_p a=head->next;
while(a->next!=head)
{
a=a->next;
}
cir_dou_list_p b=create_node(0,element);
b->next=a->next;
b->prev=a;
a->next=b;
head->len++;
}
//任意位置插入
void insert_position(cir_dou_list_p head,int position,int element)
{
if(head==NULL)
{
printf("入参为空..\n");
return;
}
if(position<1)
{
printf("输入的位置不合理..\n");
return;
}
cir_dou_list_p a=head;
for(int i=0;i<position-1;i++,a=a->next)
{
if(a->next==head)
{
printf("输入的位置不合理..\n");
return;
}
}
if(a==head)
{
printf("输入的位置不合理..\n");
return;
}
cir_dou_list_p b=create_node(0,element);
b->next=a->next;
b->prev=a;
a->next=b;
if(b->next!=head)
{
b->next->prev=b;
}
head->len++;
}
//输出
void show_list(cir_dou_list_p head)
{
if(empty(head)<0)
return;
cir_dou_list_p a=head->next;
while(a!=head)
{
printf("%d",a->data);
if(a->next!=head)
printf("<==>");
a=a->next;
}
putchar(10);
}
//头删
void delete_head(cir_dou_list_p head)
{
if(empty(head)<0)
return;
cir_dou_list_p a=head->next;
head->next=a->next;
if(a->next->prev!=head)
{
a->next->prev=head;
}
free(a);
a=NULL;
head->len--;
}
//链表的逆置
void reverse_list(cir_dou_list_p head)
{
if(empty(head)<0)
return;
cir_dou_list_p a=head->next;
if(a->next==head)
{
printf("只有一个节点,不用逆置..\n");
return;
}
cir_dou_list_p p=a->next;
cir_dou_list_p q=p;
a->next=head;
while(p!=head)
{
p=p->next;
q->next=head->next;
q->prev=head;
head->next=q;
q->next->prev=q;
q=p;
}
}
二、栈
cpp
#include"head.h"
struct zhan* create_zhan()
{
struct zhan* a=(struct zhan*)malloc(sizeof(struct zhan));
if(a==NULL)
{
printf("空间申请失败..\n");
return NULL;
}
bzero(a->data,sizeof(a->data));
a->top=-1;
return a;
}
//入栈
void insert(struct zhan* a,int element)
{
if(a==NULL)
{
printf("入参为空\n");
return;
}
if(a->top<MAX)
{
a->top++;
a->data[a->top]=element;
return;
}
printf("栈已满\n");
}
//输出
void show(struct zhan* a)
{
if(a==NULL||a->top==-1)
{
printf("栈不存在或者栈已满..\n");
return;
}
for(int i=a->top;i>=0;i--)
{
printf("data[%d]=%d\n",i,a->data[i]);
}
}
void delete(struct zhan* a)
{
if(a==NULL||a->top==-1)
{
printf("栈不存在或者栈已满..\n");
return;
}
if(a->top>-1)
{
a->top--;
}
}
void destory(struct zhan** a)
{
if(*a==NULL)
{
printf("栈不存在..\n");
return;
}
free(a);
a=NULL;
}
三、顺序表和链表的区别
-
顺序表:空间利用率有浪费,无碎片
优点:无额外指针开销,每个元素仅存储数据本身,空间密度高(空间密度 = 数据占用空间 / 总占用空间)。
-
缺点:静态顺序表:若元素数量远小于容量,会浪费大量连续内存;动态顺序表:扩容时会预留冗余空间(如 ArrayList 扩容为 1.5 倍),仍有潜在浪费;需申请 "连续的大块内存",若内存中无足够连续空间,即使总空闲内存足够,也无法创建顺序表。
-
链表:空间利用率灵活,有碎片
-
缺点:离散存储会产生 "内存碎片"(大量小而无用的内存块),长期使用可能影响内存效率。每个节点需额外存储指针(单链表每个节点多占 4 字节 / 8 字节,双向链表多占 8 字节 / 16 字节),空间密度低;
-
优点:容量动态增长,无需提前预留空间,元素数量 = 内存占用(除指针外)。无需连续内存,可利用离散的小内存块,内存利用率更高;