zoukankan      html  css  js  c++  java
  • 浅谈数据结构之线性表链式存储(二)

      前面我们所讲的线性表的顺序存储结构,它是有优缺点,最大的缺点是插入与删除时需移动大量的元素,这显然需要耗费许多时间。这时,我们就引入线性表的链式存储结构,它的特点是:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意味着,这些数据可以存在内存中未被占用的任意位置上,即当线性表进行插入与删除时就不需要移动大量的元素了,节约了时间。

      链式结构中,除了需要存储数据元素的信息外,还要存储它的后继元素的存储地址。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。这两部分信息组成数据元素的存储映像,称为“结点”;n个结点链接成一个链表,我们称之为“单链表”。注意:链表的第一个结点的存储位置叫做头指针,整个链表的存取是从头指针开始的;同时我们规定链表的最后一个结点指针为“空”(通常用“NULL”表示)。有时,为了方便对链表进行操作,在单链表的第一个结点前附设一个结点,称为“头结点”,头结点的数据域可以不用存储任何信息,指针域存储指向第一个结点的指针。对于一个单链表来说,进行一系列插入、删除、初始化、置空等操作是非常重要的。下面,我们来看看单链表是如何进行插入与删除等操作,具体操作源代码如下所示:  

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #define OK 1
      5 #define ERROR 0
      6 #define TRUE 1
      7 #define FALSE 0
      8 
      9 #define MAXSIZE 100         /* 存储空间初始分配量 */
     10 
     11 typedef int Status;         /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
     12 typedef int ElemType;       /* ElemType类型根据实际情况而定,这里假设为int */
     13 
     14 
     15 Status visit(ElemType c)
     16 {
     17     printf("%d ",c);
     18     return OK;
     19 }
     20 
     21 typedef struct Node
     22 {
     23     ElemType data;
     24     struct Node *next;
     25 }Node;
     26 typedef struct Node *LinkList;          /* 定义LinkList */
     27 
     28 /* 初始化顺序线性表 */
     29 Status InitList(LinkList *L) 
     30 { 
     31     *L=(LinkList)malloc(sizeof(Node));  /* 产生头结点,并使L指向此头结点 */
     32     if(!(*L))                           /* 存储分配失败 */
     33             return ERROR;
     34     (*L)->next=NULL;                    /* 指针域为空 */
     35 
     36     return OK;
     37 }
     38 
     39 /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
     40 Status ClearList(LinkList *L)
     41 { 
     42     LinkList p,q;
     43     p=(*L)->next;           /*  p指向第一个结点 */
     44     while(p)                /*  没到表尾 */
     45     {
     46         q=p->next;
     47         free(p);
     48         p=q;
     49     }
     50     (*L)->next=NULL;        /* 头结点指针域为空 */
     51     return OK;
     52 }
     53 
     54 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
     55 int ListLength(LinkList L)
     56 {
     57     int i=0;
     58     LinkList p=L->next;     /* p指向第一个结点 */
     59     while(p)                        
     60     {
     61         i++;
     62         p=p->next;
     63     }
     64     return i;
     65 }
     66 
     67 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
     68 /* 操作结果:用e返回L中第i个数据元素的值 */
     69 Status GetElem(LinkList L,int i,ElemType *e)
     70 {
     71     int j;
     72     LinkList p;         /* 声明一结点p */
     73     p = L->next;        /* 让p指向链表L的第一个结点 */
     74     j = 1;              /*  j为计数器 */
     75     while (p && j<i)    /* p不为空或者计数器j还没有等于i时,循环继续 */
     76     {   
     77         p = p->next;    /* 让p指向下一个结点 */
     78         ++j;
     79     }
     80     if ( !p || j>i ) 
     81         return ERROR;   /*  第i个元素不存在 */
     82     *e = p->data;       /*  取第i个元素的数据 */
     83     return OK;
     84 }
     85 
     86 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
     87 /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
     88 Status ListInsert(LinkList *L,int i,ElemType e)
     89 { 
     90     int j;
     91     LinkList p,s;
     92     p = *L;   
     93     j = 1;
     94     while (p && j < i)     /* 寻找第i个结点 */
     95     {
     96         p = p->next;
     97         ++j;
     98     } 
     99     if (!p || j > i) 
    100         return ERROR;      /* 第i个元素不存在 */
    101     s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */
    102     s->data = e;  
    103     s->next = p->next;     /* 将p的后继结点赋值给s的后继  */
    104     p->next = s;           /* 将s赋值给p的后继 */
    105     return OK;
    106 }
    107 
    108 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    109 /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
    110 Status ListDelete(LinkList *L,int i,ElemType *e) 
    111 { 
    112     int j;
    113     LinkList p,q;
    114     p = *L;
    115     j = 1;
    116     while (p->next && j < i)    /* 遍历寻找第i个元素 */
    117     {
    118         p = p->next;
    119         ++j;
    120     }
    121     if (!(p->next) || j > i) 
    122         return ERROR;           /* 第i个元素不存在 */
    123     q = p->next;
    124     p->next = q->next;          /* 将q的后继赋值给p的后继 */
    125     *e = q->data;               /* 将q结点中的数据给e */
    126     free(q);                    /* 让系统回收此结点,释放内存 */
    127     return OK;
    128 }
    129 
    130 /* 初始条件:顺序线性表L已存在 */
    131 /* 操作结果:依次对L的每个数据元素输出 */
    132 Status ListTraverse(LinkList L)
    133 {
    134     LinkList p=L->next;
    135     while(p)
    136     {
    137         visit(p->data);
    138         p=p->next;
    139     }
    140     printf("
    ");
    141     return OK;
    142 }
    143 
    144 int main()
    145 {        
    146     LinkList L;
    147     ElemType e;
    148     Status i;
    149     int j,k;
    150     
    151     i=InitList(&L);
    152     printf("1.初始化L后:ListLength(L)=%d
    ",ListLength(L));
    153     
    154     for(j=1;j<=6;j++)
    155             i=ListInsert(&L,1,j);
    156     printf("2.在L的表头依次插入1~6后:L.data=");
    157     ListTraverse(L); 
    158     printf("ListLength(L)=%d 
    ",ListLength(L));
    159 
    160     i=ClearList(&L);
    161     printf("3.清空L后:ListLength(L)=%d
    ",ListLength(L));
    162     
    163     for(j=1;j<=10;j++)
    164             ListInsert(&L,j,j);
    165     printf("4.在L的表尾依次插入1~10后:L.data=");
    166     ListTraverse(L); 
    167     
    168     ListInsert(&L,1,0);
    169     printf("5.在L的表头插入0后:L.data=");
    170     ListTraverse(L); 
    171     printf("ListLength(L)=%d 
    ",ListLength(L));
    172 
    173     j=5;
    174     ListDelete(&L,j,&e); 
    175     printf("7.删除第%d个的元素值为:%d
    ",j,e);
    176     printf("依次输出L的元素:");
    177     ListTraverse(L);
    178     
    179     ListInsert(&L,5,4);
    180     printf("8.插入第5个元素值后,依次输出L的值:L.data=");
    181     ListTraverse(L); 
    182     
    183     return 0;
    184 }
  • 相关阅读:
    排列组合例题分析
    短信微服务+springboot+redis整合,动态获取短信验证码
    mac版idea 2018.3.5版 永久激活教程
    windows版idea 2018.3.5版 永久激活教程
    深入理解 Java 垃圾回收机制
    如何写代码 —— 编程内功心法
    并发与并行的区别
    Lua语法要点
    android 手机上运行图像算法
    OPENCL 错误码
  • 原文地址:https://www.cnblogs.com/mix88/p/6111537.html
Copyright © 2011-2022 走看看