今天学习了链表的三种重要操作:尾插法创建单链表、头插法创建不带头节点单链表,以及双向链表的基本实现。这些是数据结构学习中的基础内容,掌握它们对理解更复杂的数据结构至关重要。
1. 尾插法创建单链表
typedef struct Lnode{
int data;
struct Lnode *next;
}lnode,*link_list;
// 尾插法:将数组元素逐个添加到链表尾部
// 特点:保持原始数据顺序,时间复杂度O(n)
void en_list(link_list *L,int *parr,int arr_len){
int j = 0;
lnode *p = *L; // p指向当前链表尾部
for(j = 0;j<arr_len;j++)
{
lnode *s = (lnode *)calloc(1,sizeof(lnode));
s->data = parr[j];
s->next = p->next;
p->next = s;
p = s; // 更新尾指针位置
}
}
// 遍历打印链表:从头节点开始逐个访问
void print_list(link_list L){
lnode *p = L;
while(p->next!=NULL)
{
p = p->next;
printf("%d ",p->data);
}
}
int main()
{
link_list L;
L = (lnode *)calloc(1,sizeof(lnode)); // 创建头节点
int insert_arr[10] = {1,2,3,4,5,6,7,8,9,0};
en_list(&L,insert_arr,10);
print_list(L);
return 0;
}
2. 头插法创建不带头节点单链表
typedef struct Lnode{
int data;
struct Lnode *next;
}lnode,*link_list;
// 头插法:新节点始终插入链表头部
// 特点:数据顺序反转,时间复杂度O(n)
void nop_head_insert(link_list *L)
{
lnode *s;
int key;
scanf("%d",&key);
while(key != 9999) // 9999为结束标志
{
s = (lnode *)malloc(sizeof(lnode));
s->data = key;
s->next = *L; // 新节点指向原链表头
*L = s; // 更新链表头指针
scanf("%d",&key);
}
}
void print_list(link_list L)
{
lnode *p = L;
while(p!=NULL)
{
printf("%d",p->data);
p = p->next;
}
}
int main()
{
link_list L = NULL; // 不带头节点,初始为空
nop_head_insert(&L);
print_list(L);
return 0;
}
3. 双向链表实现
typedef struct Lnode{
int data;
struct Lnode *prior,*next;
}lnode,*link_list;
// 在指定位置插入节点
void en_list(link_list *L,int posi,int key)
{
lnode *s = (lnode *)calloc(1,sizeof(lnode));
s->data = key;
lnode *p = *L;
int j = 0;
// 定位到插入位置的前一个节点
while(p->next !=NULL && j<posi-1)
{
p = p->next;
j++;
}
// 双向指针连接:维护前驱和后继关系
if(p->next != NULL)
{
p->next->prior = s; // 原后继节点的前驱指向新节点
}
s->next = p->next; // 新节点后继指向原后继
s->prior = p; // 新节点前驱指向当前节点
p->next = s; // 当前节点后继指向新节点
}
// 初始化链表头节点
void init_list(link_list *L) {
(*L)->next = NULL;
(*L)->prior = NULL;
}
// 正向遍历打印链表
void print_list(link_list L)
{
lnode *p = L->next; // 跳过头节点
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
}
int main()
{
link_list L = (link_list)malloc(sizeof(lnode));
init_list(&L); // 初始化头节点
en_list(&L,1,1); // 在位置1插入数据1
en_list(&L,2,2); // 在位置2插入数据2
en_list(&L,3,3); // 在位置3插入数据3
print_list(L); // 输出:1 2 3
return 0;
}
尾插法适合保持数据原始顺序的场景,头插法适合需要逆序处理的场景,而双向链表则提供了更灵活的遍历和操作能力。
2180

被折叠的 条评论
为什么被折叠?



