数据结构之链表的常见操作

双向链表的常见操作有链表节点的创建,有序插入,查找,排序,删除与释放,打印等,其精髓在于头指针的灵活使用,以及合理的链表遍历。以下程序为具体函数实现,main函数和头文件自行脑补吧。

#include <stdio.h>

#include <stdlib.h>
#include "double_link.h"


//有序插入节点

//被double_link_create 函数调用

STU *double_link_insert(STU *head, STU *p_new)  

{

//如果传进来的头指针指向空,那么就让头指针指向传进来的p_new

if(head == NULL){//空链表

head = p_new;

//前后指向都为空,表示此时链表中只有p_new一个节点

p_new->next = NULL;
p_new->prep = NULL;
}

else{

//如果传进来的不是空链表,则通过遍历链表找到p_new的位置

STU *p_mov = head;

//while内的程序即为遍历链表的过程,满足不满足其中一个条件时停止循环

while((p_new->id >= p_mov->id) && (p_mov->next != NULL)){
p_mov = p_mov->next;

}

//跳出循环的可能性分为以下两种

//第一种为遍历过程中找到了序号大于新节点的p_mov,此时把新节点插入在当前p_mov节点的前面,以保证按顺序插入

if(p_new->id < p_mov->id){
p_new->next = p_mov;
p_mov->prep->next = p_new;
p_new->prep = p_mov->prep;
p_mov->prep = p_new;
}

else{

//第二种是找到最后一个节点还是没有找到比新节点序号大的,此时新节点插在最后

p_mov->next = p_new;
p_new->prep = p_mov;
p_new->next = NULL;
}

}

//注意此时一定要返回头指针,便于后续利用头指针遍历链表

return head;
}

//创建链表的函数
STU *double_link_create(void)
{
STU *head = NULL;
//头指针必须要在最后返回
STU *ptemp = NULL;
int n=0;
while(1){
//创建空间节点
ptemp = (STU*)malloc(sizeof(STU));
if(ptemp == NULL){
perror("malloc node");
break;
}


//向新建节点结构体输入数据
printf("please input id name score:\n");
scanf("%d %s %d",&ptemp->id,ptemp->name,&ptemp->score);
getchar();


//判断是否结束
if(strcmp(ptemp->name,"quit") == 0){
free(ptemp);
ptemp = NULL;
break;
}
//节点添加到链表
head = double_link_insert(head,ptemp);
}
return head;
}


void double_link_delete(STU **head, int id)
{
STU *p_mov = *head;
if(*head == NULL){
return;
}
while(p_mov->id != id && p_mov->next != NULL){
p_mov = p_mov->next;

}

//删除节点时遍历结果分一下几种可能

if(p_mov->id != id && p_mov->next == NULL){//没有找到ID对应的节点,直接返回
printf("not found id\n");
return;
}
if(p_mov == *head){//找到头节点
if(p_mov->next){
p_mov->next->prep = NULL;
*head = p_mov->next;
}
else{
p_mov->prep->next = NULL;
}
}
else if(p_mov->id == id && p_mov->next != NULL){//找到中间节点
p_mov->prep->next = p_mov->next;
p_mov->next->prep = p_mov->prep;
}
else{//p_mov指向尾节点
p_mov->prep->next = NULL;
}
free(p_mov);//把删除掉的节点内存释放掉
}


STU * double_link_remove_first(STU *head)
{
STU *p = NULL;
if(head == NULL)
return NULL;
p = head;//p用来保存头节点,便于后面free掉删除的头节点
if(head->next != NULL)//如果头节点不是尾节点
head->next->prep = NULL;

head = head->next;
free(p);
return head;//这里说明一下,如果函数实参传进来的是头指针的地址,即二级指针,则不需要有返回值,因为通过指向指针1的指针2可以改变指针1的指向。
}


STU * double_link_free(STU *head)
{
while(head){
head = double_link_remove_first(head);
}
return head;
}
void double_link_print(STU *head)
{
STU *p_mov = head;
STU *p_save;
if(head == NULL){
return ;
}
while(p_mov != NULL){
printf("id:%d,name:%s,score:%d\n",p_mov->id,p_mov->name,p_mov->score);
p_save = p_mov;//保存最后一个节点,可用于倒序打印
p_mov = p_mov->next;
}
//p_mov == NULL;

printf("***********************\n");

//此为倒着打印的实现过程

while(p_save){
printf("id:%d,name:%s,score:%d\n",p_save->id,p_save->name,p_save->score);
p_save = p_save->prep;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值