乐趣区

关于数据结构:线性表的链式表示单链表

1、定义:

通过一组任意的存储单元来存储线性表中的数据元素。为了建设数据元素之间的线性关系,对每个链表节点,除了寄存元素本身的信息外,还须要寄存一个指向下一个节点

构造体:

typedef int ElemType;
typedef struct LNode {       // 定义单链表节点类型
    ElemType data;           // 每个节点寄存一个数据元素
    struct LNode *next;      // 指针指向下一个节点
} LNode, *LinkList;          // 强调这是一个单链表应用 LinkList,强调节点应用 LNode*

2、创立一个单链表

2.1 用头插法建设单链表

新节点插入到以后列表的表头:

代码实现:

/**
 * 用头插法建设单链表
 * @param L
 * @return
 */
LinkList List_HeadInsert(LinkList &L) {  // 逆向建设单链表
    LNode *s;
    int x;
    L = (LinkList) malloc(sizeof(LNode));  // 创立头节点
    L->next = NULL;                        // 初始为空链表
    scanf("%d", &x);                 // 输出节点的值
    while (x != 9999) {                     // 输出 9999 示意完结
        s = (LNode *) malloc(sizeof(LNode)); // 创立新节点
        s->data = x;
        s->next = L->next;
        L->next = s;                        // 将新节点插入表中,L 为头指针
        scanf("%d", &x);
    }
    return L;
}

采纳头插法建设单链表时,读入数据的程序与生成的链表中的元素的程序式相同的

2.2 用尾插法建设单链表

新节点插入到以后列表的表尾,该办法须要一个尾指针指向链表的最初一个节点,图中未画出尾指针:

代码实现:

/**
 * 用尾插法建设单链表
 * @param L
 * @return
 */
LinkList List_TailInsert(LinkList &L) {      // 正向建设单链表
    int x;                                  // 设 ElemType 为整型
    L = (LinkList) malloc(sizeof(LNode));    // 建设头节点
    LNode *s, *r = L;                          // r 为表尾指针
    scanf("%d", &x);                  // 输出节点的值
    while (x != 9999) {s = (LNode *) malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;                               // r 指向新的表尾节点
        scanf("%d", &x);
    }
    r->next = NULL;                         // 尾节点指针置空
    return L;
}

3、基本操作

3.1 在指定节点前插入元素

实现原理图:

代码实现:

/**
 * 前插操作,在 p 节点之前插入元素 e
 * @param p
 * @param e
 * @return
 */
bool InsertPriorNode(LNode *p, ElemType e) {if (p == NULL) {return false;}
    LNode *s = (LNode *) malloc(sizeof(LNode));
    if (s == NULL) {return false;}
    s->next = p->next;
    p->next = s;          // 新节点 s 连到 p 之后
    s->data = p->data;    // 将 p 中元素复制到 s 中
    p->data = e;        // p 中的元素改为 e
    return true;
}

3.2 在指定节点后插

代码实现:

/**
 * 后插操作,在 p 节点之后插入元素 e
 * @param p
 * @param e
 * @return
 */
bool InsertNextNode(LNode *p, ElemType e) {if (p == NULL) {return false;}
    LNode *s = (LNode *) malloc(sizeof(LNode));
    if (s == NULL) {       // 内存调配失败
        return false;
    }
    s->data = e;        // 用节点 s 保留数据元素 e
    s->next = p->next;  // 留神先后顺序
    p->next = s;
    return true;
}

3.3 按位序删

代码实现:

/**
 * 按位序删除,带头结点
 * @param L
 * @param i
 * @param e
 * @return
 */
bool ListDelete(LinkList &L, int i, ElemType e) {if (i < 1) {return false;}
    LNode *p;       // 指针 p 指向以后扫描到的节点
    int j = 0;      // 以后 p 指向的是第几个节点
    p = L;            // L 指向头节点,头节点是第 0 个节点,不存数据
    while (p != NULL && j < i - 1) {  // 循环找到第 i-1 个节点
        p = p->next;
        j++;
    }
    if (p == NULL) {       // i 值不非法
        return false;
    }
    if (p->next == NULL) {   // 第 i - 1 个节点之后已无其余节点
        return false;
    }
    LNode *q = p->next;     // 令 q 指向被删除的节点
    e = q->data;            // 用 e 返回元素的值
    p->next = q->next;      // 将 * q 节点从链中断开
    free(q);                // 开释节点的存储空间
    return true;
}

3.4 按位查找

/**
 * 按位查找,返回第 i 个元素,带头节点
 * @param L
 * @param i
 * @return
 */
LNode *GetElem(LinkList L, int i) {if (i < 0) {return NULL;}
    LNode *p;       // 指针 p 指向以后扫描到的节点
    int j = 0;      // 以后 p 指向的是第几个节点
    p = L;          // L 指向头节点,头节点是第 0 个节点,不存数据
    while (p != NULL && j < i) {    // 循环找到第 i 个节点
        p = p->next;
        j++;
    }
    return![image.png](/img/bVcSqxv)
退出移动版