1、设计链表
//1、设计数据结点
typedef int ElemType_t;
typedef struct node{
ElemType_t data;//数据域
struct node *prev;//上一个地址
struct node *next;//下一个地址
}Node_t;
//设计链表管理结构体---头节点
struct list{
Node_t *head; //存储链表的数据首结点
Node_t *tail; //存储链表的数据尾结点
int nodeNumber; //存储结点的数量
};
2、申请结点并初始化
/*
函数功能:申请一个新结点并且初始化,把新节点的地址返回
返回值:
参数:
*/
Node_t *new_node(struct list* listHead,ElemType_t inputData)
{
//1、申请新结点的内存空间
Node_t *newNode = malloc(sizeof(Node_t));
if(newNode == NULL)
{
perror("malloc newNode error");
return NULL;
}
//2、初始化
newNode->data = inputData;
newNode->prev = NULL;
newNode->next = NULL;
//结点的数量+1
listHead->nodeNumber++;
return newNode;
}
3、创建链表
/*
函数功能:创建一条链表
返回值:
参数:
*/
struct list* create_list()
{
//1、申请链表的头节点的内存空间并且初始化
struct list *listHead = malloc(sizeof(struct list));
if(listHead == NULL)
{
perror("malloc listHead error\n");
return NULL;
}
listHead->head = NULL;
listHead->tail = NULL;
listHead->nodeNumber = 0;
//2、从键盘上输入数据进行初始化
printf("请输入数据:");
while(1)
{
ElemType_t inputData;
int ret = scanf("%d",&inputData);
if(ret != 1 || inputData == -1)//退出条件
break;
//1)新建一个结点并且初始化
Node_t *newNode = new_node(listHead,inputData);
if(newNode == NULL)
{
printf("new_node error\n");
return NULL;
}
//2)如果当前链表是空,那么新建的这一个结点是链表的首结点,同时也是尾结点
if(listHead->head == NULL) //从无到有
{
listHead->head = newNode;
listHead->tail = newNode;
}
else //从少到多
{ //链表的尾结点的next成员指向新结点
listHead->tail->next = newNode;
//新结点的prev成员存储,原来链表的尾结点的地址
newNode->prev = listHead->tail;
//b更新链表的尾结点
listHead->tail = newNode;
}
}
//3、返回整条链表的头节点的地址
return listHead;
}
4、尾插法
/*
函数功能:尾插法
返回值:
参数:
*/
int insert_nodeToList_tail(struct list *listHead,ElemType_t inputData)
{
//1、判断listHead是否有效
if(listHead == NULL)
{
printf("listHead is NULL,%s error\n",__FUNCTION__);
return -1;
}
//2、新建结点并且初始化
Node_t*newNode = new_node(listHead,inputData);
if(newNode == NULL)
{
printf("new_node error\n");
return -1;
}
//如果当前链表没有数据结点,那么新建的这一个结点是链表的首结点也是尾结点
if(listHead->head == NULL)//从无到有
{
listHead->head = listHead->tail = newNode;
return 0;
}
//第一步:原来链表的尾结点里面的next成员存储 新结点的地址
listHead->tail->next = newNode;
//第二步:新节点的prev成员,指向原来链表的尾结点
newNode->prev = listHead->tail;
//第三步:更新尾结点
listHead->tail = newNode;
return 0;
}
5、头插法
/*
函数功能:头插法
返回值:
参数:
*/
int insert_nodeToList_head(struct list *listHead,ElemType_t inputData)
{
//1、判断listHead是否有效
if(listHead == NULL)
{
printf("listHead is NULL,%s error\n",__FUNCTION__);
return -1;
}
//2、新建结点并且初始化
Node_t*newNode = new_node(listHead,inputData);
if(newNode == NULL)
{
printf("new_node error\n");
return -1;
}
//如果当前链表没有数据结点,那么新建的这一个结点是链表的首结点也是尾结点
if(listHead->head == NULL)//从无到有
{
listHead->head = listHead->tail = newNode;
return 0;
}
//第一步:新结点的next成员存储原来链表的首结点的地址
newNode->next = listHead->head;
//第二步:原来链表的首结点里面的prev成员存储新结点的地址
listHead->head->prev = newNode;
//第三步:更新头结点
listHead->head = newNode;
return 0;
}
6、查找
/*
函数功能:查找
返回值:
参数:
*/
bool find_nodeToList(struct list *listHead,ElemType_t findData)
{
if(isEmpty(listHead))
{
printf("isEmpty ,%s error\n",__FUNCTION__);
return false;
}
bool isFindFlag = falag;
//遍历链表,挨个元素与findData进行比较
Node_t *p = listHead->head;
while(p)
{
if(p->data == findData)
{
isFindFlag = true;
break;
}
p = p->next;
}
return isFindFlag;
}
7、修改
/*
函数功能:修改
返回值:
参数:
*/
bool update_nodeToList(struct list *listHead,ElemType_t srcData,ElemType_t updata)
{
if(isEmpty(listHead))
{
printf("isEmpty ,%s error\n",__FUNCTION__);
return false;
}
//遍历链表,找到你要值尾srcData的结点--找到你要修改的结点
Node_t *p = listHead->head;
while(p)
{
if(p->data == srcData)
{
break;
}
p = p->next;
}
//如果没有找到,直接返回false
if(p == NULL)
{
return false;
}
//4、找到了,直接修改数据
p->data = updata;
return true;
}
8、删除
中间删除
尾删除
头删除
/*
函数功能:删除
返回值:
参数:
*/
bool delete_nodeToList(struct list *listHead,ElemType_t delData)
{
if(isEmpty(listHead))
{
printf("isEmpty ,%s error\n",__FUNCTION__);
return false;
}
//如果你当前删除的结点是首结点
if(listHead->head->data == delData)
{
Node_t *delNode = listHead->head;
//第一步:更新首结点
listHead->head = listHead->head->next;
//第二步:删除结点断链接
delNode->next = NULL;
//第三步:新的首结点的Prev成员指向NULL
listHead->head->prev = NULL;
//第四步:释放删除结点的内存空间
free(delNode);
listHead->nodeNumber--;
return true;
}
//2、遍历链表,先找到你要删除的那个结点
Node_t* p = listHead->head;
bool isFindFlag = false;
while(p)
{
if(p->data == delData)
{
isFindFlag = true;
break;
}
p = p->next;
}
if(isFindFlag == false)
return false;
if(p == listHead->tail)
{
//第一步:更新尾结点
listHead->tail = p->prev;
//第二步:尾结点断链接
listHead->tail->next = NULL;
//第三步:删除结点断链接
p->prev = NULL;
//第四步:释放删除结点的内存空间
free(p);
}
else
{
p->prev->next = p->next;
p->next->prev = p->prev;
p->next = NULL;
P->prev = NULL;
free(p);
}
listHead->nodeNumber--;
return true;
}