笔试面试常见的链表操作

</pre>链表涉及到大量的指针操作,实际写代码时,很容易出错。本文对常见的一些链表操作进行整理。<pre name="code" class="cpp">#include <iostream>
#include<vector>
#include<stdlib.h>
#include<stack>

using namespace std;
//****************************************//
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
ListNode* creatlist(vector<int> a,int n);
ListNode* creatnode(int val);
void Fprint_linklist(ListNode *head);//从头到尾打印链表
void Bprint_linklist(ListNode *head);//从尾到头打印链表
void delete_exit_node(ListNode **head,ListNode* node);//删除链表中某个存在的节点,要求时间复杂度为O(1)
void delete_val(ListNode **head,int val);//删除链表中数据值等于给定值的节点
ListNode* get_bkth_node(ListNode *head,int k);//获得链表中的倒数第K个节点
ListNode* reverse_linklist(ListNode **head);//反转链表,返回值反转以后链表的头结点
ListNode* first_common_node(ListNode* head1,ListNode* head2);//寻找链表的第一个公共节点,并返回公共节点
                                       //寻找两个链表的第一个公共点
int main()
{
    const int num1=8;
    const int num2=10;
    vector<int> A(num1);
    vector<int> B(num2);
    srand(1);
    for(int i=2;i<num1;i++){

        A[i]=rand()%100;
    }
    for(int i=2;i<num2;i++){

        B[i]=rand()%200;
    }


    //********创建链表测试********//
   ListNode* head1=creatlist(A,num1);
   ListNode* head2=creatlist(B,num2);
   ListNode* node1=head1;
   ListNode* node2=head2;
   ListNode* comm_node=new ListNode(88);
   while(node1->next!=NULL)
        node1=node1->next;
   while(node2->next!=NULL)
        node2=node2->next;
        node1->next=comm_node;
        node2->next=comm_node;
   cout<<"正向打印链表1: "<<endl;
   Fprint_linklist(head1);//正向打印链表
   cout<<endl;
   cout<<"正向打印链表2:  "<<endl;
   Fprint_linklist(head2);//正向打印链表
   cout<<endl;
   cout<<"反向打印单链表1:";
   Bprint_linklist(head1);//反向打印链表
   cout<<endl;
   cout<<"寻找两个链表的第一个公共节点: "<<endl;


  ListNode* p=first_common_node(head1,head2);
   cout<<"第一个公共节点的值为:  "<<p->val<<endl;
   cout<<endl;
   cout<<"反转链表"<<endl;
   head1=reverse_linklist(&head1);//反转链表
   Fprint_linklist(head1);
   cout<<endl;

   cout<<"取得倒数第k个节点测试: ";
   cout<<endl;
   ListNode *knode=get_bkth_node(head1,2);
   cout<<"第k个节点的值为:"<<knode->val<<endl;
   cout<<endl;

   cout<<"测试删除某个固定的节点: ";
    ListNode* node_delete=head1;
    delete_exit_node(&head1,node_delete);
    Fprint_linklist(head1);
    cout<<endl;

    cout<<"测试删除等于固定值的节点:";
    delete_val(&head1,41);
   Fprint_linklist(head1);
}


//函数功能:采用头插法创建链表
ListNode* creatlist(vector<int> a,int n){
    if(a.size()==0||n<=0)
    return NULL;
    ListNode *head=NULL;
    for(int i=0;i<n;i++){
        ListNode *node=creatnode(a[i]);
        if(head==NULL){
            head=node;
        }
        else{

            node->next=head;
            head=node;
        }

    }
    return head;
}

//函数功能:创建节点
ListNode* creatnode(int val){
ListNode *p=new ListNode(val);
return p;
}


//函数功能:从头到尾打印链表
void Fprint_linklist(ListNode *head){
    if(head==NULL)
        return ;
    ListNode *p=head;

    while(p){
        cout<<p->val<<" ";
        p=p->next;
    }
    cout<<endl;
}



/*函数功能:从尾到头反向打印链表
时间复杂度为:o(n)
空间复杂度为:o(n),使用了一个栈做为存储空间
*/
void Bprint_linklist(ListNode *head){
    if(head==NULL)
        return ;
    stack<ListNode*> temp;
    ListNode *node=head;

     while(node!=NULL){
        temp.push(node);
        node=node->next;
     }
     while(!temp.empty()){

        ListNode *m=temp.top();
        temp.pop();
        cout<<m->val<<" ";
    }
     cout<<endl;
}


/*函数功能:删除链表中某个存在的节点,要求时间复杂度为O(1)
算法思想:通过拷贝要删除节点的后继节点的数据,然后删除后继节点即可,考虑特殊节点:尾节点处理*/
void delete_exit_node(ListNode **head,ListNode* node){
    if(head==NULL||*head==NULL||node==NULL)
        return ;
    //要删除的节点不是尾节点
    if(node->next!=NULL){
        ListNode *q=node->next;
        node->val=node->next->val;
        node->next=q->next;
        delete q;
        q=NULL;
    }
    //链表中只有头结点
    else if(*head==node){
      delete node;
        node=NULL;
      *head=NULL;
    }
    //对于尾节点的处理还是不太明白;
    else {
      ListNode *p=*head;
      while(p->next!=node)
        p=p->next;
      p->next=node->next;
      delete node;
      node=NULL;
    }
}


/*函数功能:删除链表中等于某个值得节点
  思路:需要先判断要删除的节点是否在链表中;
        若在则将值等于给定值得节点全部删除;
        否则删除失败
*/
void delete_val(ListNode **head,int val){
    if(head==NULL||*head==NULL){
        cout<<"链表中不存在值等于"<<val<<"的节点"<<endl;
        return ;
    }
    ListNode *pre=NULL;
    ListNode *curr=*head;
    ListNode *pnext=curr->next;
    int flag=0;
    while(curr!=NULL){
        if(curr->val==val){
            //要删除的是头结点
            if(curr==*head){
                *head=pnext;
                 delete curr;

            }
            else{
                pre->next=pnext;
                delete curr;

                }
        flag=1;//用于标识链表中是否存在等于给定值的节点
        curr=pnext;
        if(curr==NULL)
            break;
        pnext=pnext->next;
        }
        else{
        pre=curr;
        curr=pnext;
        if(curr==NULL)
            break;
        pnext=pnext->next;
        }
    }

    if(flag==0)
        cout<<"链表中不存在值等于"<<val<<"的节点 ";
    else
        cout<<"删除节点值为"<<val<<"的节点 ";
}
/*函数功能:删除链表中倒数第k的节点
   思想:设置两个指针,均指向头结点,让一个指针先走k步,然后另外一个指针开始移动,直到第一个指针到达链表的结尾
   假设链表总长为n,第二个指针实际上走了n-k步,即指向倒数第k个节点*/
ListNode* get_bkth_node(ListNode *head,int k){

    if(head==NULL)
        return NULL;
    ListNode *node1=head;
    ListNode *node2=head;
    for(int i=0;i<k;i++){
        node1=node1->next;
        if(node1==NULL)//如果链表本身的长度就小于k
            return NULL;
    }
    while(node1!=NULL){
        node1=node1->next;
        node2=node2->next;

    }
    return node2;
}

/*函数功能:反转链表*/
ListNode* reverse_linklist(ListNode **head){
  if(head==NULL||*head==NULL)
    return NULL;
  if((*head)->next==NULL)
    return *head;
    ListNode *pre=NULL;
    ListNode *curr=*head;
    ListNode *pnext=curr->next;
   while(curr!=NULL){

    curr->next=pre;
    *head=curr;
    pre=curr;
    curr=pnext;
    if(curr==NULL)
        break;
    pnext=pnext->next;
   }
   return *head;

}
/*函数功能:寻找两个链表的第一个公共节点*/
ListNode* first_common_node(ListNode* head1,ListNode* head2){
    if(head1==NULL||head2==NULL)
        return NULL;
    int len1=0,len2=0;
    ListNode *node1=head1;
    ListNode *node2=head2;
    while(node1!=NULL){
       ++len1;
       node1=node1->next;
    }
    while(node2!=NULL){
        ++len2;
        node2=node2->next;
    }
    int dvalue=len1-len2;
    ListNode *temp=NULL;
    ListNode *node=NULL;
    if(dvalue>=0){
       temp=head1;
       node=head2;
    }
    else{
        dvalue=len2-len1;
        temp=head2;
        node=head1;

    }
    while(dvalue){

        temp=temp->next;
        --dvalue;
    }
    while(temp!=NULL){
        if(temp==node)
            return node;
        temp=temp->next;
        node=node->next;
    }
    cout<<"两个链表不存在公共节点"<<endl;
   return NULL;
}




代码运行结果:





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值