//Common.h
#ifndef _COMMON_H_
#define _COMMON_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <vld.h>
#include <malloc.h>
#include <assert.h>
typedef int ElemType;
#endif
//dclist.h
#ifndef _DCLIST_H_
#define _DCLIST_H_
#include "Common.h"
//带头节点的双向循环链表
//定义节点
typedef struct DCListNode{
ElemType data;
struct DCListNode* next;
struct DCListNode* prev;
}DCListNode;
typedef DCListNode* DCList;
//声明
void DCListInit(DCList *phead);
void DCListPushBack(DCList *phead,ElemType x);
void DCListPopBack(DCList* phead);
void DCListPushFront(DCList* phead,ElemType x);
void DCListPopFront(DCList* phead);
void DCListShow(DCList phead);
size_t DCListLength(DCList phead);
ElemType DCListFront(DCList phead);
ElemType DCListBack(DCList phead);
void DCListInerstByVal(DCList phead, ElemType key);
void DCListEraseByVal(DCList phead, ElemType key);
DCListNode* DCListFind(DCList phead, ElemType key);
void DCListSort(DCList phead);
void DCListReverse(DCList phead);
void DCListEraseAll(DCList phead, ElemType key);
void DCListClear(DCList* phead);
void DCListDestory(DCList* phead);
/
//实现
DCListNode* _Buynode(ElemType v = ElemType())//初始化为0
{
//申请头结点 和节点(自循环)
//有了头结点就不用考虑头结点不存在的情况
DCListNode* _S= (DCListNode*)malloc(sizeof(DCListNode));
assert(_S != NULL);
_S->data = v;
_S->next = _S->prev = _S;
return _S;
}
void DCListInit(DCList *phead)
{
//疑问?为什么不用断言
//让头指针指向头结点
*phead = _Buynode();
}
void DCListPushBack(DCList *phead, ElemType x)
{
assert(phead != NULL);
//申请新的节点
DCListNode* s = _Buynode(x);
DCListNode* head = *phead;
s->next = head;
s->prev = head->prev;
s->prev->next = s;
head->prev = s;
}
void DCListPopBack(DCList* phead)
{
assert(phead != NULL);
DCListNode* head = *phead;//头结点
//注意判空
if (head->next == head)
{
return;
}
//先找到最后一个节点
DCListNode* p = head->prev;
p->prev->next = head;
head->prev = p->prev;//p->next->prev 相当于 head->prev
free(p);
}
void DCListPushFront(DCList* phead, ElemType x)
{
assert(phead != NULL);
DCListNode* head = *phead;
//申请新的节点
DCListNode* s = _Buynode(x);
s->next = head->next;
s->prev = head;
s->prev->next = s;
s->next->prev = s;
}
void DCListPopFront(DCList* phead)
{
assert(phead != NULL);
DCListNode* head = *phead;
//判空
if (head->next == head)
{
return;
}
DCListNode* s = head->next;
head->next = s->next;//s->prev->next=s->next
s->next->prev = head;
free(s);
}
void DCListShow(DCList phead)
{
assert(phead != NULL);
DCListNode* head = phead->next;
//注意这里的循环条件以及head
while (head!= phead)
{
printf("%d->", head->data);
head = head->next;
}
printf("Over!\n");
}
size_t DCListLength(DCList phead)
{
assert(phead != NULL);
DCListNode* head = phead->next;
size_t size = 0;
while (head != phead)
{
size++;
head = head->next;
}
return size;
}
ElemType DCListFront(DCList phead)
{
assert(phead != NULL);
//判空 疑问这里的phead为什么不用加*
/*if (phead->next == phead)
{
return;
}*/
assert(phead->next != NULL);
return phead->next->data;
}
ElemType DCListBack(DCList phead)
{
assert(phead != NULL);
assert(phead->next != phead);
return phead->prev->data;
}
void DCListInerstByVal(DCList phead, ElemType key)
{
assert(phead != NULL);
//构建节点
DCListNode* s = _Buynode(key);
//不能用find查找是因为find是查找相等的
//或者自己进行查找,再进行插入
DCListNode* head = phead->next;
while (head != phead&&head->data<key)
{
head = head->next;
}
//符合所有情况
s->next = head;
s->prev = head->prev;
s->next->prev = s;
s->prev->next = s;
}
void DCListEraseByVal(DCList phead, ElemType key)
{
assert(phead != NULL);
//第一个结点
DCListNode* head = phead->next;
//查找
DCListNode* p = DCListFind(phead, key);
//没有找到和链表为空的情况find中都考虑了
if (p == NULL)
{
return;
}
//删除
p->next->prev = p->prev;
p->prev->next = p->next;
free(p);
}
DCListNode* DCListFind(DCList phead, ElemType key)
{
assert(phead != NULL);
DCListNode* s = phead->next;
//考虑链表为空的时候的情况
while (s != phead&&s->data !=key)
{
s = s->next;
}
//当其遍历一遍之后发现没有找到时,会回到头结点,此时和链表为空的情况一样
if (s == phead)
{
return NULL;
}
return s;
}
//排序思路:先断开链接,节点是否链路完 向后走,寻找位置进行链路
void DCListSort(DCList phead)
{
assert(phead != NULL);
//只有一个节点时,不需要进行逆置
if (DCListLength(phead) == 1)
{
return;
}
//断开连接 注意!!还是有两个指向没断开
DCListNode* p = phead->next;;
DCListNode* q = p->next;
p->next = phead;
phead->prev = p;
//说明节点还没有链路完成
while (q != phead)
{
p = q;
q = q->next;
//其它节点进行按值插入
DCListNode* tmp = phead->next;
//寻找位置 考虑有多个数据已经插入好了
while (tmp != phead&&p->data >tmp->data)
{
tmp = tmp->next;//如果存在一个以上的节点,就得完后走寻找插入位置
}
p->next = tmp;
p->prev = tmp->prev;
p->next->prev = p;
p->prev->next = p;
}
}
void DCListReverse(DCList phead)
{
assert(phead != NULL);
//只有一个节点时,不需要进行逆置
if (DCListLength(phead) == 1)
{
return;
}
//断开连接
DCListNode* p = phead->next;;
DCListNode* q = p->next;
p->next = phead;
phead->prev = p;
//排除只有一个节点 疑问
while (q != phead)
{
p = q;
q = q->next;
p->next = phead->next;
p->prev = phead;
p->next->prev = p;
p->prev->next = p;
}
}
void DCListEraseAll(DCList phead, ElemType key);
void DCListClear(DCList* phead)
{
assert(phead != NULL);
//找到第一个节点 然后一个一个释放
DCListNode* head = (*phead)->next;
//考虑没有节点以及已经遍历完一遍
while (head != *phead)
{
head->prev->next = head->next;
head->next->prev = head->prev;
free(head);
head = (*phead)->next;//注意!!! 更新head 让其指向下一个
}
}
void DCListDestory(DCList* phead)
{
assert(phead != NULL);
DCListClear(phead);
free(*phead);
*phead = NULL;//预防野指针
}
#endif
//mian.cpp
#include "dclist.h"
int main()
{
DCList list;
DCListInit(&list);
system("pause");
return 0;
}