1.自己实现双向循环链表的代码
a.创建
b.创建点
c.头插
d.尾插
e.按位置插入
d :头删;尾删;按位置删除。
g.按位置查找返回值
3.整理链表和顺序表的优缺点
#include "double.h"
//1、创建双向链表
node_p create_double()
{
node_p H=(node_p)malloc(sizeof(node));
if(H==NULL)
return NULL;
H->pri=H;
H->next=H;
H->len=0;
return H;
}
//2、创建结点
node_p create_node(int data)
{
node_p new_node=(node_p)malloc(sizeof(node));
if(new_node==NULL)
{
printf("申请空间失败\n");
return NULL;
}
new_node->data=data;
new_node->pri=NULL;
new_node->next=NULL;
return new_node;
}
//3、判空
int empty_double(node_p H)
{
if(H==NULL)
return -1;
return H->next==NULL?1:0;
}
//4、头插
void insert_head(node_p H,int value)
{
if(H==NULL)
{
printf("入参为空\n");
return;
}
node_p new=create_node(value);
new->next=H->next;
new->pri=H;
H->next->pri=new;
H->next=new;
}
//5.尾插
void insert_tail(node_p H,int value)
{
if(H==NULL)
return;
node_p p=H;
while(p->next!=H)
p=p->next;
node_p new=create_node(value);
p->next->pri=new;
new->pri=p;
new->next=p->next;
p->next=new;
H->len++;
}
//6.输出
void show_loop_double(node_p H)
{
if(H==NULL)
{
printf("入参为空\n");
return;
}
node_p p=H->next;
while(p->next!=H)
{
printf("%d <-> ",p->data);
p=p->next;
}
printf("H\n");
}
//7.任意位置插入
void insert_pos(node_p H,int pos,int value)
{
if(H==NULL)
return;
if(pos<=0)
return;
int i=0;
node_p p=H;
for(;inext)
{
if(i>0&&p==H)
{
printf("插入位置不合理\n");
}
}
node_p new=create_node(value);
new->next=p->next;
new->pri=p;
p->next->pri=new;
p->next=new;
}
//8、头删
void dele_head(node_p H)
{
if(H==NULL)
{
printf("入参为空\n");
return;
}
node_p dele = H->next;
if(dele->next!=H)
{
dele->next->pri=H;
}
H->next =dele->next;
free(dele);
H->len--;
}
//9、尾删
void dele_tail(node_p H)
{
if(H==NULL)
{
printf("入参为空\n");
return;
}
node_p p=H;
while(p->next!=H)
{
p=p->next;
}
node_p dele=p->next;
p->pri->next=H;
H=p->pri;
free(dele);
H->len--;
}
//10、按位删除
void dele_pos(node_p H,int pos)
{
if(H==NULL)
return;
if(empty_double(H))
return;
if(pos<=0)
return;
int i=0;
node_p p=H;
for(;inext);
if(p==H)
{
printf("删除位置不合理\n");
return;
}
p->next->pri=p->pri;
p->pri->next=p->next;
free(p);
H->len--;
}
//11、按值查找返回位置
int search_value(node_p H,int value)
{
if (H == NULL) {return -1;}
if (empty_double(H)) {return -2;}
int i = 1;
node_p p = H->next;
while (p != H)
{
if (p->data == value) {
return i;
}
p = p->next;
i++;
}
return -3;
}
//12、按位置修改元素
void update_pos(node_p H,int pos,int new_value)
{
if(H==NULL){return;}
if(empty_double(H)){return;}
if(pos<=0){return;}
int i;
node_p p=H;
for(i=0;inext)
{
if(i>0&&p==H)
{
printf("插入位置不合理\n");
return;
}
}
p->data=new_value;
}
#ifndef __DOUBLE_H__
#define __DOUBLE_H__
#include
#include
typedef struct node
{
union
{
int len;
int data;
};
struct node *pri;
struct node *next;
}node,*node_p;
//1、创建双向链表
node_p create_double();
//2、创建结点
node_p create_node(int data);
//3、判空
int empty_double(node_p H);
//4、头插
void insert_head(node_p H,int value);
//5.尾插
void insert_tail(node_p H,int value);
//6、输出
void show_loop_double(node_p H);
//7、任意位置插入
void insert_pos(node_p H,int pos,int value);
//8、头删
void dele_head(node_p H);
//9、尾删
void dele_tail(node_p H);
//10、按位删除
void dele_pos(node_p H,int pos);
//11、按值查找返回位置
int search_value(node_p H,int value);
//12、按位置修改元素
void update_pos(node_p H,int pos,int new_value);
#endif
#include "double.h"
int main()
{
node_p H=create_double();
//头插6个数
printf("头插6个数后:\n");
insert_head(H,6);
insert_head(H,12);
insert_head(H,13);
insert_head(H,14);
insert_head(H,15);
insert_head(H,16);
show_loop_double(H);
//尾插
printf("尾插后:\n");
insert_tail(H,3);
show_loop_double(H);
//任意位置插入
printf("在第10个位置插入100:\n");
insert_pos(H,10,100);
printf("在第3个位置插入24:\n");
insert_pos(H,3,24);
show_loop_double(H);
//头删
printf("头删后:\n");
dele_head(H);
show_loop_double(H);
//尾删
printf("尾删后:\n");
dele_tail(H);
show_loop_double(H);
//按位置删除
printf("删除第3个后:\n");
dele_pos(H,3);
show_loop_double(H);
//按值查找返回位置
printf("查找值12,位置结果:");
printf("%d\n",search_value(H,12));
//按位置修改
printf("修改第2个位置的值为18:\n");
update_pos(H,2,18);
show_loop_double(H);
}
2.C语言链表与顺序表优缺点
顺序表(数组)
优点
随机访问效率高:借助下标,能在 O (1) 时间复杂度内迅速访问任意元素。
内存空间连续:这一特性有利于 CPU 缓存预取,可提升访问速度。
存储密度大:每个元素仅存储数据本身,无需额外的指针域,空间利用率高。
实现简单:基本操作如初始化、访问元素等易于实现。
缺点
插入和删除效率低:若要在中间或头部进行插入、删除操作,平均需要移动 O (n) 个元素。
大小固定:静态数组的大小在编译时就已确定,难以动态调整;动态数组虽可调整大小,但调整过程(如重新分配内存、复制元素)开销较大。
内存分配问题:如果分配的空间过大,会造成内存浪费;若分配空间过小,又需频繁扩容。
链表(以单链表为例)
优点
动态扩展灵活:可以按需动态分配和释放内存,适合处理元素数量不确定的情况。
插入和删除效率高:在已知前驱节点的前提下,插入和删除操作只需 O (1) 的时间复杂度。
内存利用率高:无需预先分配大块连续内存,能有效利用碎片化的内存空间。
缺点
不支持随机访问:要访问链表中的某个元素,必须从表头开始遍历,时间复杂度为 O (n)。
存储密度低:每个节点除了存储数据,还需额外存储指针域,增加了空间开销。
缓存局部性差:由于节点在内存中是离散存储的,不利于 CPU 缓存预取,访问速度会受到影响。
实现复杂:需要管理内存分配和指针操作,容易出现内存泄漏或悬空指针等问题