• 线性表的链式存储结构


    1 n个结点链结成一个链表,即为线性表的链式存储结构,由于每一个结点只包含一个指针域,因此称为单链表。
    链表中第一个结点的存储位置成为头指针,那么整个链表的存取就必须是从头指针开始了。
    有时候会在单链表的第一个结点前附设一个结点,称为头结点。
    头指针与头结点的区别:
    头指针:
    (1)头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针。
    (2)头指针具有标识作用,所以常用头指针冠以链表的名字。
    (3)无论链表是否为空,头指针都不为空。头指针是链表的必要元素。
    头结点:
    (1)头结点是为了操作的统一和方便而设立的,放在第一个元素的结点之前,其数据域一般无意义。
    (2)有了头结点,对在第一个元素结点前插入或者删除第一个结点,其操作与其它结点的操作就统一了。
    (3)头结点不是链表的必需元素。

    2 线性表单链表的存储结构

    typedef struct Node {
        ElemType data;
        struct Node *next;
    } Node;
    typedef struct Node *LinkList;    //定义LinkList

    3 (1) 用e返回L中第i个元素的值

    typedef struct Node *pNode;
    
    Status getElem(LinkList L, int i, ElemType *e) {
    int j = 1;
    pNode p;        //定义一个指向结点的指针
    p = L->next;    //p指向单链表的第一个结点
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    if (!p || j > i) {
        return ERROR;
    }
    *e = p->data;
    return OK;
    }

    (2) 在单链表的第i个位置之前插入新的数据元素e

    Status ListInsert(LinkList *L, int i, ElemType e) {
    int j = 1;
    pNode p, s;
    p = *L;            //p指向单链表的第一个结点
    while (p && j < i) {    //寻找第i个结点
        p = p->next;
        ++j;
    }
    if (!p || j > i) {
        return ERROR;      //第i个元素不存在
    }
    s = (pNode)malloc(sizeof(Node));    //生成新的结点
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
    }

    (3) 删除单链表中第i个数据元素,并用e返回其值

    Status ListDelete(LinkList *L, int i, ElemType *e) {
      int j = 1;
      pNode p, q;
      p = *L;
      if (p) {
        while(p->next && j < i) {
            p = p->next;
            ++j;
        }
        if (!p->next || j > i) {
            return ERROR;
        }
        q = p->next;
        p->next = q->next;
        *e = q->data;
        free(q);
        return OK;
      }
      return ERROR;
    }

    (4)时间复杂度为O(n).

    3 单链表的整表创建
    (1)随机产生n个元素的值,建立带表头结点的单链表L(头插法)

    void CreateListHead(LinkList *L, int n) {
    
      LinkList p;
    
      *L = (LinkList)malloc(sizeOf(Node));    
      *L->next = NULL;    //先创建一个带头结点的单链表
    
      for (int i = 0; i < n; i ++) {
    
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand()%100 + 1;    //随机生成100以内的数字
        p->next = (*L)->next;
        (*L)->next = p;          //插入到表头
      }
    }

    (2) 随机产生n个元素的值,建立带表头结点的单链表L(尾插法)

    void CreateListTail(LinkList *L, int n) {
    
        LinkList p, r;
    
        *L = (LinkList)malloc(sizeof(Node));
        r = *L;      //r指向尾结点
    
        for (int i = 0; i < n; i ++) {
    
        p = (LinkList)malloc(sizeof(Node));
      p->data = rand()%100 + 1;
    
      r->next = p;     //将表尾的结点指向新结点
      r = p;        //将当前的新结点定义为尾结点
      }
      r->next = NULL;
    }    

    4 单链表的整表删除(链表L带头结点)

    Status ClearList(LinkList *L) {
      LinkList p,q;
      p = (*L)->next;    //p指向第一个结点
      while(p) {
        q = p->next;
        free(p);
        p = q;
      }
      (*L)->next = NULL;    //头指针的指针域为空
      return OK;
    }
  • 相关阅读:
    python并发之concurrent.futures
    Twisted 简介
    Python进程、线程、协程的对比
    协程的优点(Python)
    python concurrent.futures
    gevent 协程 使用
    python高性能代码之多线程优化
    python并发编程之多进程、多线程、异步和协程
    Java——动态代理
    NHibernate之旅(14):探索NHibernate中使用视图
  • 原文地址:https://www.cnblogs.com/muzijie/p/5617054.html
Copyright © 2020-2023  润新知