# 单链表面试题总结（一）

struct ListNode
{
ListNode(int x):mval(x),pnext(NULL){}
int mval;
ListNode * pnext;
};

 void InitList(ListNode *phead)
{
}


1.单链表的头插

  bool Insert_head(ListNode* phead,int x)
{
ListNode * p = (ListNode *)malloc(sizeof(ListNode));
p->mval = x;
return true;
}


.2.单链表的尾插

 bool Insert_tail(ListNode* phead,int x)
{
ListNode * p = (ListNode*)malloc(sizeof(ListNode));
for(;q->pnext != NULL;q=q->pnext);//比头插多了一次向后遍历找到最后一个节点
p->mval = x;
p->pnext = q->pnext;
q->pnext = p;
return true;
}


3.单链表的查找

    ListNode* Search(ListNode *phead,int x)
{
for(;p->pnext != NULL;p=p->pnext)
{
if(p->mval == x)//如果是查找前驱，p->pnext->val == x
{
return p;
}
}
return NULL;
}


4.查找待删除节点的前驱

ListNode* SearchPrev(ListNode *phead,ListNode* BeDelete)
{
if(phead == NULL || BeDelete == NULL) return NULL;
for(;p->pnext != NULL;p=p->pnext)
{
if(p->pnext == BeDelete)
{
return p;
}
}
return NULL;
}



5.单链表的删除
（1） O(n)的时间复杂度删除：

    void DeleteNode(ListNode *phead,ListNode* BeDelete)
{
if(phead == NULL || BeDelete == NULL) return ;

ListNode* q= BeDelete;//****要重新定义一个节点指向待删除的节点
p->pnext = q->pnext;//使待删除节点的前一个节点指向待删除节点的后一个节点
free(q);//删除

}


（2) O(1)的时间复杂度删除

 void DeleteListNode(ListNode * phead,ListNode *BeDelete)
{
if(phead == NULL || BeDelete == NULL) return ;
if(BeDelete->pnext != NULL)//1.要删除节点的下一个节点不是尾节点，即不是空
{
ListNode *p = BeDelete->pnext;//p是待删除节点的下一个节点
BeDelete->mval = p->mval;
BeDelete->pnext = p->pnext;
delete p;
p = NULL;//删除后置空
}
{
delete BeDelete;
BeDelete = NULL;//只有一个节点就还得把这个头节点置空****
}
else //链表中有多个节点，要删除的是尾节点
{
for(;p->pnext != NULL;p=p->pnext)//让p走到链表尾的上一个节点处
{
if(p == BeDelete)    break;
}
p->pnext = BeDelete->pnext;//BeDelete->pnext其实就是NULL
delete BeDelete;
BeDelete = NULL;
}
}


6.单链表的正序打印

    void Show(ListNode *phead)
{
for(;p != NULL;p=p->pnext)
{
cout<<p->mval<<" ";
}
cout<<endl;
}

7.（1）从尾到头打印链表，用栈

void PrintListReverse(ListNode *phead)//这个没有返回，直接打印
{
stack<ListNode*> st;
while(p != NULL)//入栈
{
st.push(p);
p = p->pnext;
}
while(!st.empty())//出栈
{
p = st.top();
st.pop();
cout<<p->mval<<" ";
}
cout<<endl;

}



（2）从尾到头打印链表，用递归，缺点是容易导致栈溢出

 vector<int> PrintListReverse_digui(ListNode *phead)//将_vec返回，在调用它的函数中进行打印
{
vector<int> _vec;
{
}
return _vec;
}

8.链表的逆置


{
}