Loading

数据结构系列1——线性表

线性表

线性表

概念

  • 相同数据类型的n个数据元素(由数据项组成)的有限序列
  • 线性表每个元素都是单个元素且类型相同,每个元素占有相同大小的空间
  • 表中元素具有抽象性,只考虑元素之间的逻辑关系,不考虑元素究竟表示什么内容
  • 线性表是逻辑结构,顺序表和链表是存储结构,注意区分

顺序表

概念

  • len表示表长,在len以外的元素没有实际意义

表示

  • 静态分配
const int MAXSIZE = 50;

struct SqList {
    int data[MAXSIZE];
    // len表示当前顺序表内的元素个数,默认为0
    int len;
};

void initList(SqList &a) {
    a.len = 0;
}
  • 动态分配
const int INITSIZE = 100;

struct SqList {
    int* data;
    int len;
};

void listInit(SqList &a) {
    a.data = (int*)malloc(INITSIZE * sizeof(int));
    // c++
    // a.data = new ElemType[INITSIZE];
    a.len = 0;
}

void listChange(SqList &a, int nlen) {
    a.data = (int*)realloc(a.data, nlen * sizeof(int));
}

基本操作

  • 插入操作(时间复杂度O(n)
bool listInsert(SqList &a, int i, int e) {
    if (i < 1 || i > a.len + 1) return false;
    if (a.len >= MAXSIZE) return false;
    for (int j = a.len; j >= i; j--) a.data[j] = a.data[j - 1];
    a.data[i - 1] = e;
    a.len++;
    return true;
}
  • 删除操作(时间复杂度O(n)
bool listDelete(SqList &a, int i, int &e) {
    if (i < 1 || i > a.len) return false;
    e = a.data[i];
    for (int j = i; j < a.len; j++) a.data[j - 1] = a.data[j];
    a.len--;
    return true;
}
  • 查找操作(时间复杂度O(n)
int listFind(SqList a, int e) {
    for (int i = 0; i < a.len; i++) {
        if (a.data[i] == e) return i + 1;
    }
    return 0;
}

单链表

表示

struct node {
    ElemType val;
    node* next;

    node() {}
    node(int v) : val(v), next(nullptr) {}
};

基本操作

  • 头插法建立单链表(时间复杂度O(n)
void headInsert(node* &L, vector<int> a) {
    node* cur;
    L = new node();
    L->next = nullptr;
    for (auto v : a) {
        cur = new node(v);
        cur->next = L->next;
        L->next = cur;
    }
}
  • 尾插法建立单链表(时间复杂度O(n)
void tailInsert(node* &L, vector<int> a) {
    L = new node();
    node *cur, *tail = L;
    for (auto v : a) {
        cur = new node(v);
        tail->next = cur;
        tail = cur;
    }
    tail->next = nullptr;
}
  • 按序号查找结点值(时间复杂度O(n)
node* getElem(node* L, int ind) {
    int cnt = 1;
    node* cur = L->next;
    if (ind == 0) return L;
    if (ind < 1) return nullptr;
    while (cur && cnt < ind) {
        cur = cur->next;
        cnt++;
    }
    return cur;
}
  • 按值查找表节点(时间复杂度O(n)
node* locateElem(node* L, int target) {
    node* cur = L->next;
    while (cur && cur->val != target) cur = cur->next;
    return cur;
}
  • 插入节点操作
void insertNode(node* L, int ind, int val) {
    node* pre = getElem(L, ind - 1);
    node* cur = new node(val);
    cur->next = pre->next;
    pre->next = cur;
}
  • 删除节点操作
void deleteNode(node*L ,int ind) {
    node* pre = getElem(L, ind - 1);
    node* temp = pre->next;
    pre->next = temp->next;
    delete(temp);
}

双链表

概念

  • 注意插入操作的步骤
    20220717113344

表示

struct dNode {
    int val;
    dNode *pre, *next;
};

循环链表

概念

  • 循环单链表判空条件:头结点的next值是否等于头指针
  • 循环双链表判空条件:头节点和pre和next值都等于头指针
  • 若只对表头和表尾进行操作,有时不设头指针只设尾指针(若仅设头指针,对表尾操作需O(n)时间复杂度,但尾指针访问表头仅需O(1)时间复杂度(r->next))

静态链表

表示

const int MAXSIZE = 50;
struct sList {
    int val;
    int next;
} L[MAXSIZE];
posted @ 2022-07-17 11:36  Patrickhao  阅读(26)  评论(0)    收藏  举报