数据结构与算法一一顺序表与单链表

一、数据结构是指数据元素的集合及元素间的相互关系和构造方法, 结构是指元素之间的关系. 在数据结构中,元素之间的相互关系称为数据的逻辑结构. 按照逻辑关系的不同将数据结构分为 线性结构和非线性结构, 线性结构包括线性表、栈、队列、串, 非线性结构包括 树、图. 数据元素及元素之间关系的存储形式称为存储结构, 可分为顺序存储和链式存储两种方式.

1. 线性结构的特点是数据元素之间一种线性关系, 即数据元素"一个接一个的排列", 这种结构主要用于描述具有单一 前驱和后继 的数据关系.

线性表的存储方式成为顺序存储和链式存储两种基本方式. 线性表的顺序存储称为 顺序表, 线性表的链式存储称为 链表.

顺序表:





相关操作:

//-------------------线性表的顺序存储-----------------------
#define MAXSIZE 20
typedef int ElemType;
typedef int Status;
typedef struct
{
    ElemType data[MAXSIZE];
    int length; // 当前线性表的长度
    
} SqList;   // 线性表的类型

// ----------获取线性表中的元素----------
// 返回值为 int型. L为结构体变量(线性表), i为要获得的元素索引, e为int型的指针变量
Status GetElem(SqList L, int i, ElemType *e)
{
    // 线性表是从 1开始的, 数组是从 0开始的
    if (L.length == 0 || i < 1 || i > L.length) {
        return 0;
    }
    *e = L.data[i-1];   // *e是指针e指向存储空间的值
    
    return 1;
}

// ----------在线性表中插入元素----------
// arg1: 结构体指针变量(线性表指针), arg2: 要插入的位置, arg3: 要插入的元素
Status ListInsert(SqList *L, int i, ElemType e)
{
    int k;
    
    if (L->length == MAXSIZE) {  //线性表满了
        return 0;
    }
    if (i < 1 || i > L->length + 1) {  // i不再范围内.(线性表从1开始)
        return 0;
    }
    if (i <= L->length) {   // 若插入的数据位置不再表尾
        // 将要插入位置后的数据元素向后移动一位
        for (k = L->length-1; k >= i-1; k--) {
            L->data[k+1] = L->data[k];
        }
    }
    // 将新元素插入
    L->data[i-1] = e;
    L->length++;    // 线性表长度+1
    
    return 1;
}

// ----------线性表中删除元素----------
Status ListDelete(SqList *L, int i, ElemType *e)
{
    int k;
    
    if (L->length == 0) {   //如果是空表
        return 0;
    }
    if (i < 1 || i > L->length) {
        return 0;
    }
    
    // 返回删除的元素.(因为数组元素是从0开始的,因此要-1)
    *e = L->data[i-1];
    
    if (i < L->length) {
        for (k = i; k < L->length; k++) {
            L->data[k-1] = L->data[k];
        }
    }
    // 线性表长度-1
    L->length--;
    
    return 1;
}

链表














//-------------------线性表的链式存储-----------------------
typedef struct Node
{
    ElemType data;  // 数据域
    struct Node* next;  // 指针域
} Node;
typedef struct Node *LinkList;

// ----------单链表的读取----------
// 初始条件: 顺序线性表L已存在. 用e返回L中第i个数据元素的值
// arg1: L是头指针  arg2: 获取第i个元素 arg3: e是int类型的指针变量
Status GetElem1(LinkList L, int i, ElemType *e)
{
    int j;
    LinkList p; // 定义指针变量p
    // 令p指向第一个结点
    p = L->next;    //头结点->next 为链表的第一个结点
    j = 1;
    
    while (p && j < i) {    // 如果结点存在 && j在i之前
        p = p->next;
        ++j;
    }
    
    if (!p || j > i) {  // 如果结点不存在 || j在i的后面
        return 0;
    }
    
    // *e为int类型存储空间的值
    *e = p->data;   // 将获取的结点保存到*e中返回.
    
    return 1;
}

// ----------单链表的插入----------
#include <mm_malloc.h>
/*
    LinkList L:  L为结构体指针,(*L)为结构体变量
    LinkList *L: L为指向结构体指针的指针. 因此(*L)就是结构体指针,(**L)就是结构体变量了
 */
// arg1: 为指向结构体指针的指针 arg2:要插入元素的位置 arg3: int型 变量e
Status ListInsert1(LinkList *L, int i, ElemType e)
{
    LinkList p, s;
    int j = 1;
    p = *L; // p指向链表的头结点
    
    // 用于寻找第i个结点.
    while (p && j < i) {    // 如果p存在 && j < i(链表的插入,需要从头开始遍历,j必须要小于i)
        p = p->next;
        ++j;
    }
    if (!p || j > i) {
        return 0;
    }
    
    s = (LinkList)malloc(sizeof(Node)); // 查找成功, 生成新结点s
    s->data = e;    //给结点数据域赋值
    // 插入操作
    s->next = p->next;  // p的后继结点 赋值给 s的后继结点(之前的p的后继结点放在s结点之后)
    p->next = s;    // 将s结点 赋值给 p的后继结点.
    
    return 1;
}

// ----------单链表的删除----------
Status ListDelete1(LinkList *L, int i, ElemType *e)
{
    LinkList p, q;
    int j = 1;
    p = *L; // P指向链表的头结点
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    if (!p || j > i) {
        return 0;
    }
    // 查找成功, 将删除的结点p->next赋值给q
    q = p->next;
    // 删除操作
    p->next = q->next;
    // 将q结点中的数据赋值给e并返回
    *e = q->data;   // 被删除结点的数据
    
    free(q);    // 释放该结点的内存
    
    return 1;
}

发布了149 篇原创文章 · 获赞 68 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/m0_37989980/article/details/80476827