双链表的实现
1.双链表结构
2.双链表定义
typedef int DClistDataType;
//定义节点类型
typedef struct DClistNode
{
DClistDataType data;
struct DClistNode* next;
struct DClistNode* prev;
}DClistNode;
typedef struct DClist
{
DClistNode* head;
}DClist;
3.接口的实现
//函数声明
void DClistInit(DClist* plist);//双向循环链表初始化、
DClistNode* creatNode(int val);//申请新的节点
void DClistPrint(DClist* plist);//打印双链表
void DClistPushBack(DClist* plist, DClistDataType val);//尾插
void DClistPopBack(DClist* plist);//尾删
void DClistPushFront(DClist* plist, DClistDataType val);//头插
void DClistPopFront(DClist* plist);//头删
DClistNode* DClistFind(DClist* plist, DClistDataType val);//查找元素
void DClistInsert(DClist* plist, DClistDataType val);//在val值前面进行插入
void DClistErase(DClistNode* pos);//删除pos位置的节点
void DClistDestory(DClist* plist);//销毁双链表
void DClistSort(DClist* plist);//链表排序
void DClistReverse(DClist* plist);//链表逆置
申请新的节点
- 申请新节点的空间
- 让节点自己先循环起来
DClistNode* creatNode(int val)
{
DClistNode* s = (DClistNode*)malloc(sizeof(DClistNode));
assert(s);
s->data = val;
s->next = s;
s->prev = s;
return s;
}
双向循环链表初始化
- 创建头结点,不存放任何数据
void DClistInit(DClist* plist)
{
plist->head = creatNode(-1);
}
尾插
- 创建新的节点
- 修改四个指针,让链表循环起来
void DClistPushBack(DClist* plist, DClistDataType val)
{
DClistNode* newNode = creatNode(val);
newNode->next = plist->head;
newNode->prev = plist->head->prev;
newNode->next->prev = newNode;
newNode->prev->next = newNode;
}
尾删
- 判断是否为空链表
- 获取最后一个节点p,将p的前后节点连接起来。达到删除的目的。
- 释放p的空间。
void DClistPopBack(DClist* plist)
{
//空链表
if (plist->head->next == plist->head)
{
return;
}
//获取最后一个节点
DClistNode* p = plist->head->prev;
p->prev->next = p->next;
p->next->prev = p->prev;
free(p);
}
头插
- 创建新的节点。
- 修改四个指针,让链表循环起来。
void DClistPushFront(DClist* plist, DClistDataType val)
{
DClistNode* newNode = creatNode(val);
newNode->next = plist->head->next;
newNode->prev = plist->head;
newNode->prev->next = newNode;
newNode->next->prev = newNode;
}
头删
- 判断是否为空链表。
- 找到第一个元素p,将头结点和p的下一个元素连接起来。
- 释放p的空间。
void DClistPopFront(DClist* plist)
{
//空链表
if (plist->head->next == plist->head)
{
return;
}
//找到第一个元素
DClistNode* p = plist->head->next;
p->prev->next = p->next;
p->next->prev = p->prev;
free(p);
}
查找链表中的值
- 找到第一个节点(头节点的下一个节点)。
- 循环找到要寻找的值。
DClistNode* DClistFind(DClist* plist, DClistDataType val)
{
DClistNode* p = plist->head->next;
while (p != plist->head && p->data != val)
{
p = p->next;
}
if (p == plist->head)
{
return NULL;
}
return p;
}
在有序链表中,按照值的大小插入
- 找到第一个节点。
- 遍历链表,寻找大于val的第一个节点拍,在p之前插入新的节点。
void DClistInsert(DClist* plist, DClistDataType val)
{
DClistNode* p = plist->head->next;
while (p != plist->head && p->data < val)
{
p = p->next;
}
DClistNode* newNode = creatNode(val);
newNode->next = p;
newNode->prev = p->prev;
newNode->next->prev = newNode;
newNode->prev->next = newNode;
}
在有序链表中,删除某个值
- 判断链表中是否有这个值。
- 如果有就将这个节点的前后节点连接起来,达到删除的目的
- 释放要删除的节点。
void DClistErase(DCList *plist, DClistDataType val)
{
DCListNode *p = DClistFind(plist, val);
if(p == NULL)
return;
p->next->prev = p->prev;
p->prev->next = p->next;
free(p);
}
链表排序
和单链表排序基本思路一样。
void DClistSort(DClist* plist)
{
if (plist->head == NULL || plist->head->next == plist->head)
{
return;
}
//断开链表
DClistNode* p = plist->head->next;
DClistNode* q = p->next;
p->next = plist->head;
plist->head->prev = p;
while(q != plist->head)
{
p = q;
q = q->next;
//寻找要插入的位置
DClistNode* pos = plist->head->next;
while(pos->next != plist->head && pos->data < p->data)
{
pos = pos->next;
}
p->next = pos;
p->prev = pos->prev;
p->next->prev = p;
p->prev->next = p;
}
}
链表逆置
和单链表的逆置思路基本相同。
void DClistReverse(DClist* plist)
{
if (plist->head == NULL || plist->head->next == plist->head)
{
return;
}
//断开链表
DClistNode* p = plist->head->next;
DClistNode* q = p->next;
p->next = plist->head;
plist->head->prev = p;
while(q != plist->head;
{
p = q;
q = q->next;
//进行头插
p->next = plist->head->next;
p->prev = plist->head;
p->next->prev = p;
p->prev->next = p;
}
}
打印双链表
void DClistPrint(DClist* plist)
{
DClistNode* p = plist->head->next;
while (p != plist->head)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
销毁双链表
void DClistDestory(DClist* plist)
{
DClistNode* p = plist->head->next;
while (p != plist->head)
{
p->next->prev = p->prev;
p->prev->next = p->next;
free(p);
p = plist->head->next;
}
free(plist->head);
plist->head = NULL;
}