C语言之双向链表(头结点与节点结构不相同)
双向链表主要注意:
1、插入节点要考虑到是在第1个节点和最后一个节点上,或者是中间,因情况不同处理的方法也不同
2、移除链表上的一个节点要考虑是1个节点还是最后一个节点上,或者是中间,因情况不同处理的方法也不同
头文件:
#ifndef __PLink2_H
#define __PLink2_H
typedef struct Node
{
char name[20];
char author[20];
float price;
int num;
struct Node *prev;
struct Node *Next;
}Node;
typedef struct Head
{
int len;
struct Node *Next;
}Head;
Head *CreateHead2(); //创建一个头结点
int DestroyHead2(Head *head); //删除整条链表
Node *CreateNode2(Node *node); //申请节点内存空间(malloc)
int DestroyNode2(Node *node); //删除节点的内存
int InsertNodeAtHead2(Head *head, Node *NewNode); //在链表中插入到第一个节点
int RemoveNode2(Head *head, Node *node); //从链表中移除一个节点,但不删除内存
Node *SreachNode2(Head *head, char *name); //搜索链表中的一个节点
int AddNode2(Head *head, Node *node); //向链表追加一个节点
int InsertNode(Head *head, Node *node, int add); //在链表指定位置上插入一个节点
int TwinLink();
int PrintfList2(Head *head);
#endif
源文件(.c):
#include "PLink2.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//创建头链表的内存空间
Head *CreateHead2()
{
Head *New = NULL;
New = (Head *)malloc(sizeof(Head) );
if(New == NULL)
{
printf("Error malloc failed\n");
return NULL;
}
memset(New, 0, sizeof(Head));
New->Next = NULL;
return New;
}
//删除整条链表的内存空间
int DestroyHead2(Head *head)
{
Node *next = NULL;
Node *node = NULL;
if(head == NULL)
{
return -1;
}
node = head->Next;
while(node != NULL)
{
next = node->Next;
DestroyNode2(node);
node = next;
}
free(head);
head = NULL;
return 0;
}
//创建申请节点内存空间(malloc)
Node *CreateNode2(Node *node)
{
Node *pstNew = NULL;
pstNew = (Node *)malloc(sizeof(Node) );
if(pstNew == NULL)
{
printf("Error malloc failed\n");
return NULL;
}
if(node != NULL)
{
memcpy(pstNew, node, sizeof(Node) );
pstNew->prev = NULL;
pstNew->Next = NULL;
}
else
{
memset(pstNew, 0, sizeof(Node));
}
return pstNew;
}
//删除节点内存空间
int DestroyNode2(Node *node)
{
if(node == NULL) return -1;
free(node);
node = NULL;
return 0;
}
//每次插入新节点都在第一个节点插入
int InsertNodeAtHead2(Head *head, Node *NewNode)
{
Node *temp = NULL;
if(head == NULL || NewNode ==NULL)
{
printf("InsertNodeAtHead is failed\n");
return -1;
}
temp = head->Next;
head->Next = NewNode;
NewNode->Next = temp;
NewNode->prev = NULL;
if(temp != NULL)
{
temp->prev = NewNode;
}
head->len++;
return 0;
}
//从链表中移除一个节点,但不删除内存
int RemoveNode2(Head *head, Node *node)
{
Node *temp = NULL;
if(head == NULL || node ==NULL) return -1;
temp = head->Next;
while(temp != NULL)
{
if(temp == node ) break;
temp = temp->Next;
}
if(temp == NULL) return -1; //空链表
if(temp->prev != NULL) //不是第一个节点
{
temp->prev->Next = temp->Next;
}
else //第一个节点
{
head->Next = temp->Next;
}
if(temp->Next != NULL) //不是最后节点
{
temp->Next->prev = temp->prev;
}
temp->prev = NULL;
temp->Next = NULL;
head->len--;
return 0;
}
//搜索链表中的一个节点
Node *SreachNode2(Head *head, char *name)
{
Node *node = NULL;
if(head == NULL || name ==NULL) return NULL;
node = head->Next;
while(node != NULL)
{
// if(node->name == name) //非字符串比较
if(strcmp(node->name, name) == 0 )
{
break;
}
node = node->Next;
}
return node;
}
//在双向链表末尾追加一个节点
int AddNode2(Head *head, Node *node)
{
Node *last = NULL;
Node *temp = NULL;
if(head == NULL || head == NULL) return -1;
temp = head->Next;
if(temp == NULL)
{
head->Next = node;
node->prev = NULL;
node->Next = NULL;
}
else
{
while(temp != NULL) //最后一个节点时,跳出循环
{
last = temp;
temp = temp->Next;
}
node->prev = last;
last->Next = node;
node->Next = NULL;
}
head->len++;
return 0;
}
//在链表指定位置上插入一个节点
int InsertNode(Head *head, Node *node, int add)
{
Node *temp = NULL;
if(head == NULL || head == NULL || add <= 0) return -1;
if(add == 1)
{
InsertNodeAtHead2(head, node);
}
else
{
temp = head->Next;
while(temp != NULL)
{
if(add == 1)
{
break;
}
add--;
temp = temp->Next;
}
if( (temp != NULL) && (add == 1) ) //插入到链表中某个节点上(2-链表最后一个)
{
node->Next = temp->prev->Next;
temp->prev->Next = node;
node->prev = temp->prev;
temp->prev = node;
}
else if( (temp == NULL) && (add == 1) ) //向链表追加一个节点
{
AddNode2(head, node);
}
else if( (temp == NULL) && (add > 1) ) //超出了插入节点的范围
{
return -1;
}
}
head->len++;
return 0;
}
测试代码:
//填写节点数据
int NodeData(Node *node, char *name, char *author, float price, int num)
{
if(node == NULL) return -1;
strcpy(node->name, name);
strcpy(node->author, author);
node->price = price;
node->num = num;
return 0;
}
//打印链表
int PrintfList2(Head *head)
{
Node *p = head->Next;
if(head == NULL) return -1;
while(p != NULL)
{
printf("%s\n", p->name);
p = p->Next;
}
printf("\n");
return 0;
}
//测试个函数功能
int TwinLink()
{
Head *head = (Head *)CreateHead2();
Node *Newnode = NULL;
Node node;
NodeData(&node, "aaa", "zhangsan", 100.05, 5); //填写链表的数据
Newnode = CreateNode2(&node); //创建一个节点并将填写的数据写入节点中
AddNode2(head, Newnode); //向链表追加一个节点
PrintfList2(head); //打印链表的数据
NodeData(&node, "bbb", "lisi", 55.44, 56);
Newnode = CreateNode2(&node);
InsertNodeAtHead2(head, Newnode); //插入一个节点到链表的第1个节点的位置上
PrintfList2(head);
NodeData(&node, "ccc", "wangwu", 22.05, 9);
Newnode = CreateNode2(&node);
InsertNode(head, Newnode, 2); //向链表插入一个节点到第2个节点的位置上
PrintfList2(head);
Newnode = SreachNode2(head, "ccc"); //在链表上搜索一个节点
RemoveNode2(head, Newnode); //在链表上移除一个节点
DestroyNode2(Newnode); //删除这个节点的内存
PrintfList2(head);
return 0;
}
测试效果图: