1. 与双向链表的初相识
首先,要明白它长什么样子:
通过观察可以发现这玩意由好几个单体组成,长度不定。欸嘿嘿,但每一个单体都是一样的啊。
————有数据,有指向上一个单体的指针,有指向下一个单体的指针,只不过首尾指向空而已。
那么这几行代码就不南个理解啦!
typedef struct Node
{
int data;//节点里存储的数据
struct Node* front;//指向前一个单体的指针
struct Node* tail; //指向后一个单体的指针
}NODE,*LPNODE;
创建一个节点就更好理解喽
LPNODE createNode(int data)
{
LPNODE newNode = (LPNODE)malloc(sizeof(NODE));//new一个节点
assert(newNode);//断言,万一没有new出来就终止
newNode->front = NULL;//就创建了一个节点,首尾指向空
newNode->tail = NULL;
newNode->data = data;//传数据
return newNode;
}
其次,我们要处理的是一个双向链表,并不是一个一个的节点,那是不是得创建一个双像链表的结构呢?必须滴。
typedef struct DList
{
LPNODE frontNode; //双向链表的首节点
LPNODE tailNode; //双向链表的尾节点
int curSize; //当前链表列表有多少个节点
}DLIST,*LPDLIST;
LPDLIST createDList() //创建一个双向链表
{
LPDLIST list = (LPDLIST)malloc(sizeof(DLIST));
assert(list);
list->frontNode = NULL;
list->tailNode = NULL;
list->curSize = 0;
return list;
}
好啦下面进入插入删除操作啦;
头部插入:
void push_front(LPDLIST list,int data)
{
if (list == NULL)//判断列表是否为NULL,NULL和’空‘两个意思哦
return;
LPNODE newNode = createNode(data);//先创建一个再插入啊
if (list->curSize == 0) //如果是空链表
{
list->frontNode = newNode; //列表的头节点就是创建的那个
list->tailNode = newNode; //欸嘿嘿,尾节点也是它哦
list->curSize++; //插入了嘛,节点数就变了+1
}
else //如果不是空链表
{
newNode->tail = list->frontNode; //先创建的节点的尾部指向列表的头节点
list->frontNode->front = newNode;//列表的头节点的指向下一个节点的指针指向新创建的节点
list->frontNode = newNode; //列表的头节点变成了新创建的节点
list->curSize++; //插入了嘛,节点数就变了+1
}
}
对于不是NULL节点插入的图像: 我画的不好看哈,将就着看吧。。。三步走
尾部插入:
void push_back(LPDLIST list, int data)
{
if (list == NULL)//判断是否为NULL链表
return;
LPNODE newNode = createNode(data);//创建节点
if (list->curSize == 0) //如果为空链表,就。和头部插入一样了
{
list->frontNode = newNode;
list->tailNode = newNode;
list->curSize++;
}
else //如果不是
{
list->tailNode->tail = newNode;//链表的尾节点的尾部指向新链表
newNode->front = list->tailNode;//新节点的头指针指向此时链表的尾节点
list->tailNode = newNode; //尾节点只有一个,,就是最后一个
list->curSize++; //插入了嘛,节点个数+1
}
}
指定位置插入: 注意注意 这里用数据充当指定位置
void push_appoin(LPDLIST list, int posData, int data)
{
if (list == NULL||list->curSize==0)
return;
if (list->frontNode->data == posData)
{
push_front(list, data);
}
else
{
LPNODE preNode = list->frontNode;//要插入的节点的前一个节点
LPNODE curNode = list->frontNode;//要插入的节点的后一个节点
while (curNode != NULL && curNode->data != posData)
{
preNode = curNode;
curNode = preNode->tail;
}
if (curNode == NULL)
{
printf("未找到指定位置,无法插入!\n");
}
else
{
LPNODE newNode = createNode(data);//创建要插入的节点
preNode->tail = newNode;//前一个节点的尾指针指向新节点
newNode->tail = curNode;//新节点的尾指针指向后一个节点
curNode->front = newNode;//后一个节点的前指针指向新节点
newNode->front = preNode;//新节点的前指针指向前一个节点
list->curSize++;
}
}
}
接下来删除的相应操作就不用多说了吧。
void pop_front(LPDLIST list)
{
if (list == NULL || list->curSize == 0)
{
printf("无法删除!链表为空\n");
return;
}
LPNODE nextNode = list->frontNode->tail; //nextNode=NULL
free(list->frontNode);
list->frontNode = nextNode; //NULL
if (nextNode != NULL)
{
nextNode->front = NULL;
}
else
{
list->tailNode = NULL;
}
list->curSize--;
}
void pop_back(LPDLIST list)
{
if (list == NULL || list->curSize == 0)
{
printf("链表为空无法删除!\n");
return;
}
LPNODE preNode = list->tailNode->front; //表尾的上一个节点
free(list->tailNode);
list->tailNode = preNode;
if (preNode != NULL)
{
preNode->tail = NULL; //当只有一个节点preNode=NULL
}
else
{
list->frontNode = NULL;
}
list->curSize--;
}
void pop_appoin(LPDLIST list, int posData)
{
if (list == NULL || list->curSize == 0)
{
printf("链表为空无法删除!");
return;
}
if (list->frontNode->data == posData)
{
pop_front(list);
return;
}
LPNODE preNode = list->frontNode;
LPNODE curNode = list->frontNode;
while (curNode != NULL&&curNode->data!=posData)
{
preNode = curNode;
curNode = preNode->tail;
}
if (curNode == NULL)
{
printf("未找到指定位置无法删除!\n");
}
else
{
if (list->tailNode == curNode)
{
pop_back(list);
}
else
{
preNode->tail = curNode->tail;
//curNode->tail是不是不空
//当删除的表尾时候,curNode->tail等于空
curNode->tail->front = preNode;
free(curNode);
curNode = NULL;
list->curSize--;
}
}
}
预祝新年快乐!!!