#include "ListWithHead.h"
//创建头节点
LWH_HeadNode * LWH_HeadNode_Create(void)
{
//直接将我们的头节点在堆上面创建 然后将其返回 用的事calloc自动初始化为0
return (LWH_HeadNode *)calloc(1,sizeof(LWH_HeadNode));
}
//创建双向链表的节点 基于数据
static LWH_Node *LWH_Node_Create(const LWH_DataType data)
{
LWH_Node * ptr = (LWH_Node *)calloc(1,sizeof(LWH_Node));
ptr ->_data = data;
return ptr;
}
//将节点插入到链表里面去 尾查
static void LWH_Node_Insertback(LWH_HeadNode * head,LWH_Node * node)
{
if(!head || !node)
return;
//什么时候需要动first 链表不存在就要动了
if(!head ->_first)
{
//你加入的节点就是第一个 也是最后一个
head ->_first = head ->_last = node;
}
else//链表存在了
{
head ->_last ->_next = node;//将这个节点接在最后一个的后面
node ->_prev = head ->_last;//这个节点的前面变成刚刚的最后一个节点
head ->_last = node;//最后一个换到node上面去
}
head ->_num++;
}
//将节点插入到链表里面去 头插
static void LWH_Node_Insertfront(LWH_HeadNode * head,LWH_Node * node)
{
if(!head || !node)
return;
if(!head ->_first)
{
//你加入的节点就是第一个 也是最后一个
head ->_first = head ->_last = node;
}
else//链表存在了
{
head ->_first ->_prev = node;//第一个节点的前面变成了node
node ->_next = head ->_first;//node的后面变成了现在的链表的第一个
head ->_first = node;//将链表的第一个转到node上面去
}
head ->_num++;
}
//将数据插入到链表里面去
void LWH_Push_Back(LWH_HeadNode * head,const LWH_DataType data)
{
LWH_Node_Insertback(head,LWH_Node_Create(data));
}
//push_front 头插 作业
void LWH_Push_Front(LWH_HeadNode * head,const LWH_DataType data)
{
LWH_Node_Insertfront(head,LWH_Node_Create(data));
}
//获取长度
int LWH_Length(LWH_HeadNode * head)
{
if(LWH_Empty(head))
return 0;
return head ->_num;
}
//做遍历指针 第一个(begin) 最后一个(rbegin) 结束(end) 下一个(next) 上一个prev 获取数据getdata
void LWH_Begin(LWH_HeadNode * head)
{
if(!head)
return;
head ->_ptr = head ->_first;
}
void LWH_Rbegin(LWH_HeadNode * head)
{
if(!head)
return;
head ->_ptr = head ->_last;
}
bool LWH_End(LWH_HeadNode * head)
{
if(!head)
return true;
return head ->_ptr == NULL;
}
void LWH_Next(LWH_HeadNode * head)
{
if(!LWH_End(head))
head ->_ptr = head ->_ptr ->_next;
}
void LWH_Prev(LWH_HeadNode * head)
{
if(!LWH_End(head))
head ->_ptr = head ->_ptr ->_prev;
}
LWH_DataType LWH_GetData(LWH_HeadNode * head)
{
if(!LWH_End(head))
return head ->_ptr ->_data;
return LWH_ERRORVALUE;
}
//判断这个链表是不是空的
bool LWH_Empty(LWH_HeadNode * head)
{
if(!head)
return true;
return head ->_num == 0;
}
//删除第一个(如果ptr正好在这里,我们需要指向下一个) 返回删除节点的数据,返回LWH_ERRORVALUE为错误
//删除最后一个(如果ptr正好在这里,我们需要指向上一个) 返回删除节点的数据,返回LWH_ERRORVALUE为错误
LWH_DataType LWH_Pop_Front(LWH_HeadNode * head)
{
if(!head || LWH_Empty(head))
return LWH_ERRORVALUE;
LWH_Node * ptr = head ->_first;//标记你要删除的节点
//如果ptr正好在这里,我们需要指向下一个
if(head ->_ptr == ptr)
head ->_ptr = ptr ->_next;
if(head ->_first != head ->_last)
{
//缩头 将新的头的前面一个删除
head ->_first = head ->_first ->_next;
head ->_first ->_prev = NULL;
//孤立ptr
ptr ->_next = NULL;
}
else//就这有这么一个 你还要删了
{
head ->_first = head ->_last = NULL;//将头和尾都指向NULL 一个元素都没有了
}
LWH_DataType data = ptr ->_data;
free(ptr);
head ->_num--;
return data;
}
LWH_DataType LWH_Pop_Back(LWH_HeadNode * head)
{
if(!head || LWH_Empty(head))
return LWH_ERRORVALUE;
LWH_Node * ptr = head ->_last;//标记你要删除的节点
//如果ptr正好在这里,我们需要指向上一个
if(head ->_ptr == ptr)
head ->_ptr = ptr ->_prev;
if(head ->_first != head ->_last)
{
//缩尾 将新的尾的后面一个删除
head ->_last = head ->_last ->_prev;
head ->_last ->_next = NULL;
//孤立ptr
ptr ->_prev = NULL;
}
else//就这有这么一个 你还要删了
{
head ->_first = head ->_last = NULL;//将头和尾都指向NULL 一个元素都没有了
}
LWH_DataType data = ptr ->_data;
free(ptr);
head ->_num--;
return data;
}
//清空
void LWH_Clear(LWH_HeadNode * head,void (*callback)(const LWH_DataType))
{
if(!head)
return;
while(!LWH_Empty(head))
{
LWH_DataType data = LWH_Pop_Back(head);
if(callback)
{
callback(data);
}
}
}
//销毁这个链表 弄完那边的head会指向NULL
void LWH_Destory(LWH_HeadNode ** head,void (*callback)(const LWH_DataType))
{
if(!head)
return;
LWH_Clear(* head,callback);
free(*head);
*head = NULL;
}
//Remove_if 删除按照规则返回true(从开始到结尾,找到的第一个删除)
//你们可以继续扩充到 Remove_if_all 将所有满足条件的删除
//返回该元素 返回LWH_ERRORVALUE为删除失败
LWH_DataType LWH_Remove_if(LWH_HeadNode * head,bool (*callback)(const LWH_DataType))
{
if(!head || !callback)
return LWH_ERRORVALUE;
//你需要一个遍历指针来找
LWH_Node * ptr = head ->_first;
while(ptr)
{
if(callback(ptr ->_data))//为真就要删除
{
LWH_DataType data = ptr ->_data;
if(ptr == head ->_first)//ptr可能是头
{
LWH_Pop_Front(head);
}
else if(ptr == head ->_last)//ptr可能是尾
{
LWH_Pop_Back(head);
}
else//删中间
{
ptr ->_prev ->_next = ptr ->_next;//当前节点的前面的后面变到了它的后面去了
ptr ->_next ->_prev = ptr ->_prev;//当前节点的后面的前面变到了它的前面去了
//现在链表就绕过了ptr重新连接起来了 ptr就可以被游离出来了
ptr ->_next = ptr ->_prev = NULL;
if(head ->_ptr == ptr)
head ->_ptr = ptr ->_next;
free(ptr);
head ->_num--;
}
return data;
}
ptr = ptr ->_next;
}
return LWH_ERRORVALUE;
}
//删除按照规则返回true(从开始到结尾,所有满足规则都要删除)
//你们可以继续扩充到 Remove_if_all 将所有满足条件的删除
//callback如果你的数据有释放的需求,请自己搞定
//这个代码是不会对你的数据进行处理的
void LWH_Remove_if_all(LWH_HeadNode * head,bool (*callback)(const LWH_DataType))
{
while(LWH_Remove_if(head,callback) != LWH_ERRORVALUE);
//这个代码效率稍低 但是简单明了 如果想提高效率
//按照上面的删除规则去删除 把while写在那个里面去 这样我们的指针不需要每次都从开头开始
}
//remove 删除迭代器指针的那个位置的节点,删除之后迭代器指针 有时间就写了
//迭代器指向下一个
LWH_DataType LWH_Remove(LWH_HeadNode * head)
{
if(!head || LWH_Empty(head) || LWH_End(head))
return LWH_ERRORVALUE;
LWH_DataType data = head ->_ptr ->_data;//保存你要返回的数据
//删除头
if(head ->_ptr == head ->_first)
{
LWH_Pop_Front(head);
}
else if(head ->_ptr == head ->_last)//删除尾
{
LWH_Pop_Back(head);
head ->_ptr = NULL;
}
else//删中间
{
LWH_Node *ptr = head ->_ptr;//先将你要删除的节点保存起来
head ->_ptr = head ->_ptr ->_next;//迭代器往后面指一个
ptr ->_prev ->_next = ptr ->_next;//当前节点的前面的后面变到了它的后面去了
ptr ->_next ->_prev = ptr ->_prev;//当前节点的后面的前面变到了它的前面去了
//现在链表就绕过了ptr重新连接起来了 ptr就可以被游离出来了
ptr ->_next = ptr ->_prev = NULL;
free(ptr);
head ->_num--;
}
return data;
}
//erase_after 将删除迭代器指针指向的后面的元素擦除 作业
LWH_DataType LWH_Erase_after(LWH_HeadNode * head)
{
LWH_Node * ptr = head ->_ptr;
//走下一个
LWH_Next(head);
LWH_Remove(head);
//迭代器再回到前面的那个节点就可以了
head ->_ptr = ptr;
}
//sort 作业,由于是基于数据进行排序,因此你要给规则
//d1 是前面节点元素 d2是后面节点元素 calback返回true的时候 d1 d2交换位置
//如果calback为空则不会排序
void LWH_Sort(LWH_HeadNode * head,bool (*callback)(const LWH_DataType d1,const LWH_DataType d2))
{
if(!head || LWH_Length(head) < 2 || !callback)//头节点不存在或者链表的长度小于2 没有必须要排序
return;
for(int i = 0;i < LWH_Length(head) - 1;i++)//总趟数 Length - 1
{
int flag = 0;//看是否交换 如果一个都没有交换 说明已经排好了 就可以退出了
//遍历指针
LWH_Node * ptr = head ->_first;
while(ptr ->_next)
{
//看条件进行交换
if(callback(ptr ->_data,ptr ->_next ->_data))
{
flag = 1;
LWH_DataType t;
t = ptr ->_data;
ptr ->_data = ptr ->_next ->_data;
ptr ->_next ->_data = t;
}
ptr = ptr ->_next;
}
if(!flag)
break;
}
}
// 返回链表中的倒数第n个元素 作业
//两个指针 一个现在前面走n步 然后再一起走 前面那个走到头了,后面的那个就是倒数第n个
//错误返回 LWH_ERRORVALUE
LWH_DataType LWH_Countdown(LWH_HeadNode * head,int n)
{
if(!head || LWH_Length(head) < n)
return LWH_ERRORVALUE;
LWH_Node * f = head ->_first;//前面一个
LWH_Node * s = head ->_first;//后面一个
//前面先走n步
for(int i = 0;i < n;i++)
{
f = f ->_next;
}
//两个人再一起走
while(f)
{
f = f ->_next;
s = s ->_next;
}
return s ->_data;
}
//merge 归并两个有序的链表 有时间就写了
//head1 和 head1 都应该是升序或者降序 归并好了的链表也是有序的
//head2 归并到 head1里面去 归并完毕 head2只会剩余一个空的头节点
//callback为比较的规则
void LWH_Merge(LWH_HeadNode * head1,LWH_HeadNode * head2,bool (*callback)(const LWH_DataType d1,const LWH_DataType d2))
{
if((!head1 || !head2))
return;
//将head2归并到head1里面去
//需要三个遍历指针
LWH_Node * p = head1 ->_first;
LWH_Node * q1 = head2 ->_first;
LWH_Node * q2 = head2 ->_first;//主要走q2
while(!LWH_Empty(head2))
{
if(!callback(p ->_data,q2 ->_data))//不满足条件 p 往后面走
{
p = p ->_next;
if(!p)//弄到最后面的后面还没有找到 那么就没得了 那么就将head2全部接到head1后面
{
head1 ->_last ->_next = head2 ->_first;
head2 ->_first ->_prev = head1 ->_last;
head1 ->_last = head2 ->_last;
head1 ->_num += head2 ->_num;
memset(head2,0,sizeof(*head2));
return;
}
}
else
{
q1 = q2;
while(q2 ->_next && callback(p ->_data,q2 ->_next ->_data))
{
q2 = q2 ->_next;
}//发现第一个不满足
head2 ->_first = q2 ->_next;
if(!LWH_Empty(head2))
{
//断开q2
head2 ->_first ->_prev = NULL;
q2 ->_next = NULL;
}
//将q1 ~ q2这一节全部接在p的前面
if(p == head1 ->_first)
{
q2 ->_next = p;
p ->_prev = q2;
head1 ->_first = q1;
}
else
{
p ->_prev ->_next = q1;
q1 ->_prev = p ->_prev;
p ->_prev = q2;
q2 ->_next = p;
q2 = head2 ->_first;//接完了 q2要弄到head2 ->_first
}
}
}
head1 ->_num += head2 ->_num;
memset(head2,0,sizeof(*head2));
}