这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战
考研算法必会
单链表与双链表
双链表的插入操作
双链表的插入操作,假定存储元素e,节点s,插入操作要注意顺序问题
s->next = p->next; //语句①
p->next->prior = s; //语句②
s->prior=p; //语句③
p->next = s; //语句④
插入实现的首要解决的问题是赋值顺序问题,假设第 4 步先执行,则 p->next 提前变成了 s,由 于在第 1 步与第 2 步之间都用到了 p->next,最终插入失败。
双链表的删除操作
如果理解了插入操作,那么删除操作就比较简单了。以双链表为例,如下图删除节点 p 流程图所示,如果要删除节点 p,则需要如下步骤:
p->prior->next = p->next; //如图①
p->next->prior = p->prior; //如图②
free(p) //释放空间,不要漏掉
//删除结点操作
LinkList DeletElem(LinkList &L,int i){
int length;
length=LinkLen(L);
if(i>0&&i<=length){
LNode *p,*q;
p=GetElem(L,i-1);
q=p->next;
p->next=q->next;
free(q);
}
}
插入与删除分析
插入操作:
最好情况 T = O(1)
最差情况 T = O(N)
平均情况 T = O(N)
删除操作: 最好情况 T = O(1)
最差情况 T = O(N)
平均情况 T = O(N)
逆置
方法一:头插法
算法思想: 修改指针即可,head 指针遍历链表不断向前移动,用 p 记录 head 的之前的 一个节点,修改各个节点指针域 next,指向 p,用一个 temp 指针指向(保存)head 的 下一个节点。
方法二:递归
递归的方式与迭代的不同之处是,递归是从链表的尾部进行处理的,遍历链表,记录末尾节 点,用 newhead 记录,作为新链表的头节点,工作指针 head 递归返回时,将 head 赋给 head->next->next,并将head->next 置为 NULL。
#include "stdio.h"
struct ListNode
{
int m_nData;
ListNode* m_pNext;
};
// pPrev pNode pNext
// 正常实现
ListNode* ReverseList(ListNode *pHead)
{
ListNode* pNode = pHead;
ListNode* pReversedHead = NULL;
ListNode* pPrev = NULL;
while(NULL != pNode)
{
ListNode* pNext = pNode->m_pNext;// 保存当前节点的下一个节点
if (NULL == pNext)
pReversedHead = pNode;// 如果下一节点为NULL,则当前节点为反转后的头节点,记录
pNode->m_pNext = pPrev;// 将当前节点的下一个节点指向已经记录的前一个节点,因为要反转嘛
pPrev = pNode;// 现在要向右错位了,前一个节点成为了当前节点
pNode = pNext;// 当前节点成为了当前节点的下一个节点
}
return pReversedHead;
}
// 递归实现
ListNode* ReverseSingle(ListNode* pNode, ListNode* pPrev)
{
if (NULL == pNode)
{
return pPrev;
}
ListNode* pNext = pNode->m_pNext;// 保存当前节点的下一个节点
pNode->m_pNext = pPrev;
return ReverseSingle(pNext, pNode);
}
ListNode* ReverseListRecursive(ListNode *pHead)
{
ListNode* pNode = pHead;
ListNode* pPrev = NULL;
return ReverseSingle(pNode, pPrev);
}
int _tmain(int argc, _TCHAR* argv[])
{
int len = 10;
ListNode *pHead = new ListNode;
pHead->m_nData = 10;
pHead->m_pNext = NULL;
ListNode *pPrev = pHead;
for (int i=0; i<len; i++)
{
ListNode *p = new ListNode;
p->m_nData = i;
p->m_pNext = NULL;
if (NULL != pPrev)
{
pPrev->m_pNext = p;
}
pPrev = p;
}
//ListNode *pReversedHead = ReverseList(pHead);
ListNode* pReversedHead = ReverseListRecursive(pHead);
return 0;
}