C++链表的实现(链表反转、合并)

本文详细介绍了如何使用C++实现链表的基本操作,包括链表的反转(通过栈和三指针法)以及如何递归地合并两个有序链表。每个部分都包含详细的步骤解释和验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0、链表的实现

class List {
public:
    ListNode *root;
    List()
    {
        root = new ListNode;
    }
    ~List(){
        delete root;
    }
    /*
     Create
     *函数功能:创建链表.
     *输入:各节点的data
     *返回值:指针head
     */
    ListNode *create() //*&是指针的引用
    {
        ListNode *p1,*p2 = nullptr;
        ListNode *head=NULL;
        
        cout<<"输入数序(以负数或0结束): ";
        int n;
        cin>>n;
        while(n>0)
        {
            p1=new ListNode;
            p1->data=n;
            p1->next=NULL;
            if(NULL==head){               //将head, p1, p2都指向头结点
                head=p1;
                p2=head;
            }else{
                p2->next=p1;
                p2=p1;
            }
            cin>>n;
        }
        root = head;
        return root;
    }
    
    
    /*
     insert
     *函数功能:在链表中插入元素.
     *输入:head链表头指针,p新元素插入位置,x新元素中的数据域内容
     *返回值:无
     */
    ListNode *insert(ListNode *head, int p, int x)
    {
        cout<<"在第"<<p<<"元素后插入"<<x<<endl;
        ListNode *tmp=head;//for循环是为了防止插入位置超出了链表长度
        for(int i=0; i<p;i++)
        {
            if(tmp==NULL){
                return head;
            }
            if(i<p-1){
                tmp=tmp->next;
            }
        }
        ListNode *tmp2=new ListNode;
        tmp2->data=x;
        tmp2->next=tmp->next;
        tmp->next=tmp2;
        return head;
    }
    
    ListNode* deleteNode(ListNode* head, int data)
    {
        ListNode* point = head;
        
        if(point->data == data)
        {
            head = head->next;
            free(point);//其实这里要有个free的,但是这是静态创建的,暂时先放下
            return head;
        }
        
        while(point->next != NULL)
        {
            if(point->next->data == data)
            {
                point->next = point->next->next;
                return head;
            }
            point = point->next;
        }
        return head;
    }
    /*
     del
     *函数功能:删除链表中的元素
     *输入:head链表头指针,pos被删除元素位置
     *返回值:被删除元素中的数据域.如果删除失败返回-1
     */
    int del(ListNode *head,int pos)
    {
        ListNode *tmp = head;
        for(int i=1;i<pos;i++)
        {
            if(tmp==NULL) return -1;
            if(i<pos-1){
                tmp=tmp->next;
            }
        }
        int ret=tmp->data;
        return ret;
    }
    // 求链表长度
    int len(){
        return len(root);
    }
    int len(ListNode *h)
    {
        int i=0;
        while(h!=NULL)
        {
            i++;
            h=h->next;
        }
        return i;
    }
    
    /*
     验证链表是否有环,如:1->2->3->4->6->5
                             ↑———8<———│
     有返回true,否则返回false
     */
    bool checkCircle(ListNode *head)
    {
        if (head == NULL) return false;
        ListNode *p = head;
        ListNode *q = head->next;
        while ( q!=NULL) {
            if (q == p) return true;
            p = p->next;
            if (q->next == NULL) return false;
            else q = q->next->next;
        }
        return false;
    }

    
    //打印节点
    void display(){
        if (!checkCircle(root)) {
            display(root);
        }else{
            cout<<"The circle Link!"<<endl;
        }
    }
    void display(ListNode *head)
    {
        for(ListNode*tmp=head;tmp!=NULL;tmp=tmp->next){
            printf("%d->",tmp->data);
        }
        printf("\n");
    }


    //反转链表,返回头结点
    ListNode* reverseList(){
        return reverseList(root);
    }
    //反转1:借用stack反转
    ListNode* reverseList(ListNode* root) {
        stack<int> stk;//定义栈
            
        ListNode *p = root;
        while (p)  //依次读取栈的内容,也就是第一步
        {
             stk.push(p->data);
             p = p->next;
        }

        p = root;
        while (p)   //依次出栈,更换链表中的数据,也就是第二步
        {
             p->data = stk.top();
             stk.pop();
             p = p->next;
         }
        return p;
    }
    
    //反转2:三指针法实现链表的反转
    ListNode* reverseList3(ListNode* pHead) {
        if(pHead==nullptr)
            return pHead;
            
        ListNode* temp=nullptr;
        ListNode* cur=pHead;
        ListNode* node=nullptr;
        while(cur!=nullptr)
        {
            node=cur->next;
            cur->next=temp;
            temp=cur;
            cur=node;
        }
        root = temp;
        return temp;
    }
    //删除链表里的重复元素
    ListNode* deleteDuplicates(ListNode* head)
    {
        ListNode* point = head;
        while(point != NULL && point->next!=NULL && point->data == point->next->data)
        {
            head = head->next;
            root = head;
            point = head;
        }
        
        while(point != NULL && point->next != NULL)
        {
            if(point->next->data == point->data)
            {
                point->next = point->next->next;
            }else{
                point = point->next;
            }
        }
        return head;
    }
};

1、链表反转

  • 1-1:借用stack反转
ListNode* reverseList(ListNode* pHead) {
    stack<int> stk;//定义栈
        
    ListNode *p = pHead;
    while (p)  //依次读取栈的内容,也就是第一步
    {
         stk.push(p->data);
         p = p->next;
    }

    p = pHead;
    while (p.root)   //依次出栈,更换链表中的数据,也就是第二步
    {
         p->data = stk.top();
         stk.pop();
         p = p->next;
     }
     return p;
}
  • 1-2:三指针法实现链表的反转

    ListNode* reverseList3(ListNode* pHead) {
        if(pHead==nullptr)
            return pHead;
            
        ListNode* temp=nullptr;
        ListNode* cur=pHead;
        ListNode* node=nullptr;
        while(cur!=nullptr)
        {
            node=cur->next;
            cur->next=temp;
            temp=cur;
            cur=node;
        }
        root = temp;
        return temp;
    }

2、合并两个有序的链表(递归)

	ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if (list2==NULL)
        {
            return list1;
        }
        if (list1==NULL)
        {
            return list2;
        }
        if (list1->val < list2->val)
        {
            list1->next = mergeTwoLists(list1->next, list2);
            return list1;
        }else
        {   
            list2->next = mergeTwoLists(list1, list2->next);
            return list2;
        }
    }

验证

int main(int argc, const char * argv[]) {
    Link link;
    link.create();
    link.display();
    
    link.insert(link.root, 2, 3);
    link.display();
    
    Node *mid = link.findMidElement(link.root);
    mid->next = link.root;
    link.display();

	link.reverseList();
    link.display();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

群野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值