数据结构与算法笔记——链表和指针运用

 

 

文章目录


前言

链表部分就是线性表的重点部分,是线性表的链式存储结构的实现,不需像顺序表一样使用大量连续的空间。


 

一、单链表

1.单链表的结构

typedef struct LNode{
    int data;
    struct LNode *next;   //尾指针
}LNode, *LinkList;        //用指针来表示一个单链表

2.初始化

带头结点的单链表的初始化的过程:创建链表指针的头结点,并创建、初始化和连接每个结点。

bool InitList(LinkList &L, int n){
    L = (LinkList )malloc(sizeof(LNode));
    if(!L)    return false;
    L->next = NULL;                //带头结点的初始化,不带头结点的只需L = NULL

    //以下实际是完成链表的插入:头插法(逆序插入)和尾插法(顺序插入),
    //头插法是指每个结点插入L后,尾插法是每个结点插入尾指针后,再移动尾指针到最后,即这个结点处
    LinkList p = L;                //初始化尾指针
    while(n--){
        LinkList m = (LinkList )malloc(sizeof(LNode));
        if(!m)    return false;
        
        scanf("%d", &m->data);   //输入
        m->next = p->next;
        p->next = m;
        p = m;
    }
    return true;
}
    

3.插入

找插入的前一个位置,若只能找到后一个位置的,可以新建一个结点,将两者的值调换,实现插入。

按位插入:

bool InsertList(LinkList &L, int i, Data e){
    if( i < 1)    return false;

    LinkList p = L;
    int j = 0;

    while( p && j < i-1){   //找到i-1的结点
        p = p->next;
        j++;
    }
    
    if(!p) return false;

    LinkList q =(LinkList )malloc(sizeof(LNode));
    if(!q) return false;
    q->s = e;

    q->next = p->next;
    p->next = q;
    return true;
}

指定节点位置前后插入:

bool PriorLNode(LinkList &p, Data e){
    LinkList q = (LinkList )malloc(sizeof(LNode));
    if(!q) return false;

    q->s = p->s;
    p->s = e;
    q->next = p->next;
    p->next =q;

    return true;
}

bool NextLNode(LinkList &p, Data e){
    LinkList q = (LinkList )malloc(sizeof(LNode));
    if(!q) return false;

    q->s = e;
    q->next = p->next;
    p->next = q;

    return true;
}

4.删除

按位删除:

bool DeleteList(LinkList &L, int i, Data &e){
    if( i < 1 ) return false;

    LinkList p = L;
    int j = 0;

    while( p && j < i-1 ){
        p = p->next;
        j++;
    }

    if(!p) return false;

    e = p->next->s;
    p->next = p->next->next;
    free(p->next);
    return true;
}

5.查询

简单略过

二、链表的问题

链表的问题大多是伴随着多指针的运用,这里也顺便总结一下双指针的用法。

1.链表的合并(归并排序merge过程)

//两递减链表,合并保留生成第三个递增的链表
int Merge(LinkList &La, LinkList &Lb, LinkList &Lc){
    LinkList pa = La->next;
    LinkList pb = Lb->next;
    Lc = (LinkList )malloc(sizeof(LNode));
    if(!Lc)
        return false;
    Lc->next = NULL;
    int cns = 0;
     //由于要求递增有序,原两个链表是递减的,
     //就不需尾插法的尾指针,直接使用头结节的头插法
    while(pa && pb){
        LinkList pc = (LinkList )malloc(sizeof(LNode));
        if(!pc) return false;
        if(pa->val > pb->val){
            pc->val = pa->val;
            pa = pa->next;
        }else if(pa->val < pb->val){
            pc->val = pb->val;
            pb = pb->next;
        }else{
            pc->val = pa->val;
            pa = pa->next;
            pb = pb->next;
        }
        cns++;
        pc->next = Lc->next;
        Lc->next = pc;
    }
    if(pb) pa = pb;
    while(pa){
        LinkList pc = (LinkList )malloc(sizeof(LNode));
        if(!pc) return false;
        pc->val = pa->val;
        pc->next = Lc->next;
        Lc->next = pc;
        pa = pa->next;
        cns++;
    }
        return true;
}

2.链表的逆置

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
      
public:   
    ListNode* ReverseList(ListNode* pHead){
        if(!pHead || !pHead->next)
            return pHead;
        ListNode *pre = NULL;
        ListNode *p = pHead;
        ListNode *next = NULL;
         
        while(p){
          next = p->next;
          p->next = pre;
          pre = p;
          p = next;
        }
        return pre;
    }
};

3.链表是否有环——块慢指针法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL || head->next == NULL)
            return false;
         
        ListNode *fast,*slow;
        fast = slow = head;
        while(fast != NULL&& fast->next != NULL){
            fast = fast->next->next; 
            slow = slow->next;
             if(slow == fast)
                return true;
        }
        return false;
    }
};

4.双指针汇总问题

1.首尾双指针:排序数组查找目标等于两数之和的两个元素

2.同向指针:快慢指针问题,滑动窗口的问题

3.反向指针:最长回文子串

4.分离双指针:合并有序数组


总结

未完待续

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值