链表的各种操作

链表的基本操作都写在下面了
具体内容写在代码注释中了

#include <stack>
#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;

struct ListNode
{
    int val;
    struct ListNode * next;
};

///增,传进来要增加尾的链表的表头
///可利用这个函数来建立链表

void create(ListNode** head, int val)
{
    ListNode * new_node = new ListNode();
    new_node->val = val;
    new_node->next = nullptr;
    if(*head==nullptr)
    {
        *head = new_node;
    }
    else
    {
        ListNode * phead = *head;
        while(phead->next!=nullptr)
        {
            phead = phead->next;
        }
        phead->next = new_node;
    }
    return ;
}

///删,删掉链表中第一个值为val的节点

void delete_node(ListNode** head, int val)
{
    if(head==nullptr||*head==nullptr)
        return ;
    ListNode* phead = *head;
    if(phead->val==val)
    {
        *head = (*head)->next;
    }
    else
    {
        while(phead->next!=nullptr)
        {
            if(phead->next->val==val)
                break;
            phead = phead->next;
        }
        if(phead->next!=nullptr&&phead->next->val==val)
        {
            phead->next = phead->next->next;
        }
    }
    return ;
}

///注意代码的鲁棒性,异常处理啊!!!!记住了呀
///倒数第k个节点,相当于只遍历一遍链表

ListNode * find_kth_tail(ListNode * head, int k)
{
    if(k==0||head==nullptr)
        return nullptr;
    ListNode * quick = head;
    ListNode * slow = head;
    for(int i=1; i<k; i++)
    {
        quick = quick->next;
        if(quick==nullptr)
            return nullptr;
    }
    while(quick->next!=nullptr)
    {
        quick = quick->next;
        slow = slow->next;
    }
    return slow;
}

///倒着打印链表,利用栈的特性,不建议用递归写,容易爆栈

void reverse_ListNode_print(ListNode * head)
{
    stack<int>s;
    while(!s.empty())
        s.pop();
    ListNode * phead = head;
    while(phead!=nullptr)
    {
        s.push(phead->val);
        phead = phead->next;
    }
    while(!s.empty())
    {
        printf("%d\n",s.top());
        s.pop();
    }
}

///利用快慢指针判断链表是否存在环

///原理:慢指针每次走一步,快指针每次走两步
///初始状态都处于链表头,同时出发,如果快指针走到表尾
///两个指针还没有相遇则证明没有环存在,如果相遇则存在环
///可类比于环形跑道

ListNode * check_ring(ListNode * head)
{
    if(head==nullptr)
        return nullptr;
    ListNode * quick = head;
    ListNode * slow = head;
    while(quick->next!=nullptr)
    {
        if(quick->next->next!=nullptr)
            quick = quick->next->next;
        else
            break;
        if(slow->next!=nullptr)
            slow = slow->next;
        else
            break;

        if(slow->val==quick->val)
            return slow;
    }
    return nullptr;
}

///计算环的长度

int len_of_ring(ListNode* start)
{
    if(start==nullptr)
        return 0;
    int len = 1;
    ListNode * tmp = start->next;
    while(tmp!=nullptr&&tmp!=start)
    {
        len++;
        tmp = tmp->next;
    }
    return len;
}

///寻找链表入口

ListNode* enter_of_ring(ListNode* head)
{
    if(head==nullptr)
        return nullptr;
    ListNode* start = check_ring(head);
    if(start==nullptr)
        return nullptr;
    int len = len_of_ring(start);
    ListNode* quick = head;
    ListNode* slow = head;
    for(int i=0; i<len; i++)
        quick = quick->next;
    while(quick!=slow)
    {
        quick = quick->next;
        slow = slow->next;
    }
    return slow;
}
///反转整个链表,返回值为反转后的表头
ListNode* reverse_list(ListNode* head)
{
    if(head==nullptr)
        return nullptr;
    if(head->next==nullptr)
        return head;
    ListNode* pre = nullptr;
    ListNode* now = head;
    ListNode* next = nullptr;
    while(now!=nullptr)
    {
        next = now->next;
        now->next = pre;
        pre = now;
        now = next;
    }
    return pre;
}

///反转相邻元素,返回值为反转后的表头

ListNode* reverse_adjacent_element(ListNode* head)
{
    if(head==nullptr)
        return nullptr;
    if(head->next==nullptr)
        return head;
    ListNode* pre = nullptr;
    ListNode* now = head;
    ListNode* next = head->next;
    ListNode* ans = next;
    while(next!=nullptr)
    {
        ///    1->2->3->4
        ///pre now next;

        if(pre!=nullptr)
            pre->next = next;
        now->next = next->next;
        next->next = now;
        pre = now;
        if(pre==nullptr)
            break;
        now = pre->next;
        if(now==nullptr)
            break;
        next = now->next;
    }
    return ans;
}

///合并两个有序链表,返回值为合并后的链表头

ListNode* merge_list(ListNode* head1, ListNode* head2)
{
    if(head1==nullptr)
        return head2;
    if(head2==nullptr)
        return head1;
    ListNode* ans = new ListNode();
    ListNode* res = ans;
    while(head1!=nullptr&&head2!=nullptr)
    {
        if(head1->val<head2->val)
        {
            ans->next = head1;
            ans = ans->next;
            head1 = head1->next;
        }
        else
        {
            ans->next = head2;
            ans = ans->next;
            head2 = head2->next;
        }
    }
    while(head1!=nullptr)
    {
        ans->next = head1;
        ans = ans->next;
        head1 = head1->next;
    }
    while(head2!=nullptr)
    {
        ans->next = head2;
        ans = ans->next;
        head2 = head2->next;
    }
    ans = nullptr;
    return res->next;
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        ListNode * head = nullptr;
        for(int i=0; i<n; i++)
        {
            int val;
            scanf("%d",&val);
            create(&head,val);
        }
        ListNode* head2 = nullptr;
        for(int i=2; i<8; i++)
            create(&head2,i);
        reverse_ListNode_print(head);
        //delete_node(&head,2);
        ListNode * tmp = find_kth_tail(head,2);
        if(tmp!=nullptr)
            printf("%d\n",tmp->val);
//        head = reverse_adjacent_element(head);
//        while(head!=nullptr)
//        {
//            printf("%d\n",head->val);
//            head = head->next;
//        }
        printf("---------\n");
        head = merge_list(head,head2);
        while(head!=nullptr)
        {
            printf("%d\n",head->val);
            head = head->next;
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值