zoukankan      html  css  js  c++  java
  • 单向动态链表

    单项链表的一些必要声明

    #include <stdio.h>
    #include <stdlib.h>
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    
    typedef int Status;
    typedef int ElemType;
    
    typedef struct LNode
    {
        ElemType data;
        struct LNode *next;
    }LNode,*LinkList;
    
    

    从表头到表尾逆向创建链表

    图示:当链表为空时的插入情况

    图示:当链表非空时的插入情况

    /**
     * 从表头到表尾逆向创建链表,包含n个节点
     * 需传入表头指针的指针,因为需要对表头指针进行重定向
     * 但凡其传入的参数需要改变原值的都需要传入其指针,包括指针本身
     * 在p节点后插入in节点方法:in先和p指向相同的后继元,p再指向in
     */
    void CreateList(LinkList * L, int n)
    {
        *L = (LinkList)malloc(sizeof(LNode)); /* 建立头结点 */
        (*L)->next = NULL;
        LinkList in;
        for( ; n>0; n--) {
            in = (LinkList)malloc(sizeof(LNode));
            scanf("%d",&in->data); /* 创建新的节点 */
            in->next = (*L)->next; /* 总是在头结点之后插入 */
            (*L)->next = in;
        }
    }
    

    从链表中获取第 i 个元素的数据

    图示:链表为空,p一开始就指向NULL,不满足直接退出

    图示:链表非空,while退出条件是ji,退出时,p刚好指向第i个节点

    图示:链表非空,但i的位置为处没有节点,while退出条件是p
    NULL,不满足

    /**
     * 从链表中获取第 i 个元素的数据。
     * 思路:可以从第一个元素开始p和j同步走,如果j=i满足退出,则p指向第i个节点
     * 若是空表,则一开始p就为空了,直接返回error
     * 若不是空表,但p到达了NULL,说明i不满足,也直接返回error
     */
    Status GetElem(LinkList L, int i, ElemType *e)
    {
        LinkList p = L->next;  /* p指向第一个元素 */
        int j = 1;             /* j从第 1 个元素开始 */
        while (p && j<i) {     /* 顺指针向后查找,直到p指向第i个元素或p为空 */
            p = p->next;       
            j++;
        }
        if(!p || j>i) 
            return ERROR;      /* 若p到达NULL,则必然没找到 */
        *e = p->data;
        return OK;
    }
    

    插入元素e到第i个位置

    图示:链表为空时插入到第一个

    图示:链表非空时,先将p索引到i-1下,然后在i-1后插入

    图示:链表非空时,插入位置刚好在表尾巴

    图示:链表非空时,插入位置超过了表尾

    /** 
     * 在第i个位置前插入e 
     * 思路: 在第i个位置前插入,则插入后将取代i的位置,原来i的位置变成i+1
     * 需先找打i-1的位置,同样让p和j同步,j=i-1时则p刚好指向i-1的位置
     */
    Status ListInsert(LinkList L, int i, ElemType e)
    {
        LinkList p,s;
        p = L;      /* 从头结点开始 */
        int j=0;
        while (p && j<i-1) { /* 寻找第i-1个结点 */
            p = p->next;
            j++;
        }
    
        if(!p || j>i-1)     /* i小于1或者大于表长加1*/
            return ERROR;
        s = (LinkList)malloc(sizeof(LNode));
        s->data = e;
        s->next = p->next;  /* s先和p指向相同的后继元 */
        p->next = s;        /* p再指向s */
        return OK;
    }
    

    删除第i个位置的元素

    图示:链表为空时没有元素可删除,显然不符合

    图示:链表不为空时,p刚好索引到i-1,while退出条件是j==i-1正常删除

    图示:链表不为空时,p刚好索引到i-1,while退出条件是p->next == NULL,则i处于NULL位置或更后面,i位置错误,不符合

    图示:删除步骤

    /**
     * 删除第i个位置的元素 
     * 思路:先索引到第i-1,这时p指向i-1,然后让q指向i临时保存起来
     * 然后断开i,即前一个不再指向它,而是指向它的后一个,最后将q释放
     */
    Status ListDelete(LinkList L, int i, ElemType * e)
    {
        LinkList p,q;
        p = L;
        int j=0;
        while(p->next && j<i-1) {   /* 寻找第i个结点并令p指向其前趋 */
            p = p->next;
            j++;        
        }
        if(!(p->next) || j>i-1) /* 删除位置不合理 */
            return ERROR;
        q = p->next;            /* 先让q指向p的后继元即要删除的位置,保存起来 */
        p->next = q->next;      /* 将删除的位置断链,即前一个不再指向它,而是指向它的后一个 */
        *e = q->data;
        free(q);
        return OK;
    }
    

    合并链表

    图示:初始条件pa,pb指针其第一个节点,Lc和pc指向La头结点,比较 pa->data <= pb->data,满足则pc链接向pa的那个节点,同时pc移到pa位置处,pa指向下一个节点

    图示:比较 pa->data <= pb->data,不满足则pc链接向pb的那个节点,同时pc移到pb位置处,pb指向下一个节点

    /**
     * 归并递增链表La和Lb得到同样递增链表Lc
     * 思路:用三个指针pa,pb,pc,初始条件pa,pb指针其第一个节点,Lc和pc指向La头结点
     * 比较 pa->data <= pb->data,满足则pc链接向pa的那个节点,pa指向下一个节点
     * 让pa,pb指向剩余链表的首部,pc总是指向Lc的最后一个节点
     */
    void MergeList(LinkList La, LinkList Lb, LinkList * Lc)
    {
        LinkList pa,pb,pc;
        pa = La->next;  /* pa,pb分别指向第一个结点 */
        pb = Lb->next;
        *Lc = pc = La; /* 用La的头结点作为Lc的头结点 */
        while(pa && pb) {
            if(pa->data <= pb->data) {
                pc->next = pa;  /* 链接小的那个 */
                pc = pa;        
                pa = pa->next;  /* 被链接的那个指向下一个 */
            }
            else {
                pc->next = pb;
                pc = pb;
                pb = pb->next;
            }
        }
        pc->next = pa ? pa : pb; /* 插入剩余段 */
        free(Lb);               /* 释放Lb的头结点 */
    }
    

    打印链表

    void printList(LinkList L)
    {
        LinkList p = L->next;  /* 指向第一个节点 */
        while (p) {            /* 不是空节点 */
            printf("%d ",p->data);
            p = p->next;
        }
        printf("
    ");
    }
    
  • 相关阅读:
    HDU 2089 不要62
    HDU 5038 Grade(分级)
    FZU 2105 Digits Count(位数计算)
    FZU 2218 Simple String Problem(简单字符串问题)
    FZU 2221 RunningMan(跑男)
    FZU 2216 The Longest Straight(最长直道)
    FZU 2212 Super Mobile Charger(超级充电宝)
    FZU 2219 StarCraft(星际争霸)
    FZU 2213 Common Tangents(公切线)
    FZU 2215 Simple Polynomial Problem(简单多项式问题)
  • 原文地址:https://www.cnblogs.com/wjundong/p/11619214.html
Copyright © 2011-2022 走看看