单链表面试题总结(一)

首先是链表的结构

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

初始化

 void InitList(ListNode *phead)
    {
         if(phead == NULL) return ;
         phead->pnext = NULL;
    }

1.单链表的头插

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

.2.单链表的尾插

 bool Insert_tail(ListNode* phead,int x)
    {
         if(phead == NULL) return false;
         ListNode * p = (ListNode*)malloc(sizeof(ListNode));
         ListNode * q=phead;
         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)
    {
         if(phead == NULL) return NULL;
         ListNode *p=phead;
         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;
         ListNode *p=phead;
         for(;p->pnext != NULL;p=p->pnext)
         {
             if(p->pnext == BeDelete)
             {
                 return p;
             }
         }
         return NULL;
    }

5.单链表的删除
(1) O(n)的时间复杂度删除:
先从头遍历,在链表中找到待删除的节点i的前一个节点h,让h的pnext指向节点i的下一个节点j,然后删除这个节点i

    void DeleteNode(ListNode *phead,ListNode* BeDelete)
    {
         if(phead == NULL || BeDelete == NULL) return ;
         ListNode * p =SearchPrev(phead,BeDelete);//待删除节点的前驱

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

    }

(2) O(1)的时间复杂度删除
把待删除节点的下一个节点的内容复制到待删除节点,然后把下一个节点删除,相当于把当前要删除的节点删除了
这个方法虽然时间复杂度小,但是要考虑的情况很多(3种):删除的是不是尾节点,这个尾节点会不会是头节点

 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;//删除后置空
         }
         else if(phead == BeDelete)//2.链表只有一个节点,既是头节点,也是尾节点
         {
             delete BeDelete;
             phead = NULL;
             BeDelete = NULL;//只有一个节点就还得把这个头节点置空****
         }
         else //链表中有多个节点,要删除的是尾节点
         {
             ListNode* p = phead;
             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)
    {
         ListNode *p = phead->next;
         for(;p != NULL;p=p->pnext)
         {
             cout<<p->mval<<" ";
         }
         cout<<endl;
    }

7.(1)从尾到头打印链表,用栈

void PrintListReverse(ListNode *phead)//这个没有返回,直接打印
    {
         ListNode *p = 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;
      assert(phead != NULL);
      if(phead->pnext != NULL)
      {
          PrintListReverse_digui(phead->pnext);
      }
      _vec.push_back(phead->mval);
      return _vec;
 }

8.链表的逆置


    ListNode* ReverseList(ListNode* phead)//逆置之后没有改变头节点,依然可以返回,不返回也可以
    {
         if(phead == NULL) return NULL;
         ListNode * p = phead->pnext;
         phead->pnext = NULL;
         ListNode* q = phead;
         while(p != NULL)
         {
             q = p->pnext;
             p->pnext = phead->pnext;
             phead->pnext = p;
             p = q;
         }
         return phead;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值