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("
    ");
    }
    
  • 相关阅读:
    深入分析 Java 中的中文编码问题
    随便写写20160411
    Linux GDB 程序调试工具使用详解
    「美国花好几亿造出太空圆珠笔后,发现苏联航天员用铅笔」的故事真实吗?
    verynginx部署
    harbor私有仓库部署
    rancher学习
    harbor部署
    zabbix-proxy docker
    NFS部署
  • 原文地址:https://www.cnblogs.com/wjundong/p/11619214.html
Copyright © 2011-2022 走看看