数据结构第三章:不带头结点的单链表操作
Posted 歌咏^0^
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构第三章:不带头结点的单链表操作相关的知识,希望对你有一定的参考价值。
目录
一、新建一个值为inputData的结点,插到链表中值为frontData的结点的前面
二、在一个有序的链表中,有序(升序)地将值为inputData的结点插入到链表中
一、新建一个值为inputData的结点,插到链表中值为frontData的结点的前面
/*
insert_nodeToList:新建一个值为inputData的结点,插到链表中值为frontData的结点的前面
如果值为frontData的结点不存在,则插在链表的尾部
如果值为frontData的结点有多个,则插在第一个的前面
如果值为frontData的结点是首结点,则使用头插
参数:
head 链表的首结点
inputData 新建结点的数据
frontData 新结点插在该结点的前面的数据
返回值:
成功 返回 链表的首结点
失败 返回 NULL
*/
struct node* insert_nodeToList(struct node *head,ElemType inputData,ElemType frontData)
{
//1、新建一个结点,并且初始化
struct node *newNode = new_node(inputData);
if(newNode==NULL)
{
printf("insert_nodeToList error\\n");
return NULL;
}
//遍历链表,找到值为frontData的结点frontNode和它的前面一个结点pre
struct node *p=head;
struct node *pre=NULL;
while(p)
{
//找到了,此时 p 就是 值为frontData的结点frontNode
if(p->data == frontData)
break;
else{//如果没有找到,则p往链表的下一个结点进行遍历
pre = p;//记录p结点的上一个结点
p = p->next;
}
}
if(p!=NULL)//找到的情况
{
if(p == head)//1、如果值为frontData的结点 是首节点 ,使用头插法,更新首结点
{
//新结点的next存储原链表的首结点地址,也就是新结点指向原来的首结点
newNode->next = head;//newNode->next = p;
head = newNode;//此时新结点就是链表的首结点
}
else{//2、值为frontData的结点在中间
newNode->next = p;
pre->next = newNode;
}
}
else{//没找到的情况(如果链表遍历完之后,没找到) p == NULL ,也就是说值为frontData的结点没有找到,新结点使用尾插
pre->next = newNode;
}
return head;
}
二、在一个有序的链表中,有序(升序)地将值为inputData的结点插入到链表中
/*
insert_nodeToList_sort:在一个有序的链表中,有序(升序)地将值为inputData的结点插入到链表中
思路:首先找到比inputData值大的第一个结点bigNode,将这个新结点插入到bigNode的前面
如果找到了
找到的结点bigNode 是首结点,使用头插
找到的结点bigNode 是中间结点,使用中间插法
如果没找到
说明新结点是最大的,那么使用尾插
参数:
head 链表的首结点
inputData 新建结点的数据
返回值:
成功 返回 链表的首结点
失败 返回 NULL
*/
struct node* insert_nodeToList_sort(struct node *head,ElemType inputData)
{
//1、新建一个结点,并且初始化
struct node *newNode = new_node(inputData);
if(newNode==NULL)
{
printf("insert_nodeToList error\\n");
return NULL;
}
//2、遍历链表,找到比inputData值大的第一个结点bigNode
struct node *p=head;
struct node *pre=NULL;
while(p)
{
if(p->data > inputData)//此时 p 就是 值比inputData大的第一个结点bigNode
break;
else{//如果没有找到,则p往链表的下一个结点进行遍历
pre = p;//记录p结点的上一个结点
p = p->next;
}
}
if(p != NULL)//如果找到了
{
#ifdef DEBUG
printf("文件:%s 当前函数:%s 第%d行 找到了\\n",__FILE__,__FUNCTION__,__LINE__);
#endif
//找到的结点bigNode也就是 p 是首结点,使用头插
if(p == head)
{
newNode->next = head;
head = newNode;
}
else{
//找到的结点bigNode 是中间结点,使用中间插法
newNode->next = p;
pre->next = newNode;
}
}
else{//如果没找到 ,也就是说 p == NULL
#ifdef DEBUG
printf("文件:%s 当前函数:%s 第%d行 没找到\\n",__FILE__,__FUNCTION__,__LINE__);
#endif
//说明新结点是最大的,那么使用尾插
pre->next = newNode;
}
return head;
}
三、在已知的链表中删除 值为 delData的结点
/*
delete_nodeToList 在已知的链表中删除 值为 delData的结点
参数:
head 链表的首结点
delData 你要删除的结点的源数据
返回值:
返回 链表的首结点
*/
struct node* delete_nodeToList(struct node *head,ElemType delData)
{
//1、遍历链表,找到值为delData的结点(待删除的结点) 和 待删除结点的上一个结点
struct node *p=head;
struct node *pre=NULL;//待删除结点的上一个结点
while(p)
{
if(p->data == delData)//找到了
{
if(p == head)//如果待删除的结点是首结点 p和head 都是存储首结点的地址
{
//1、先更新首结点
head = head->next; //p->next;
//2、待删除结点的next赋值为NULL
p->next = NULL;
//3、释放待删除结点的内存空间 p == 0x1010
free(p); //p == 0x1010
//p = NULL;
p = head;
}
else{//待删除结点在中间 ,也就是中间结点 //p 此时就是待删除结点 pre待删除结点的上一个结点
//1、待删除结点的上一个结点指向待删除结点的下一个结点
pre->next = p->next;
//2、待删除结点的next赋值为NULL
p->next = NULL;
//3、释放待删除结点的内存空间
free(p);
p = pre->next;
}
}
else{
pre = p;
p = p->next;
}
}
return head;
}
以上是关于数据结构第三章:不带头结点的单链表操作的主要内容,如果未能解决你的问题,请参考以下文章