zoukankan      html  css  js  c++  java
  • 线性表

    线性表(linear_list)是最常用且最简单的一种数据结构。

    一个线性表是n个数据元素的有限序列,它有两种表示形式:顺序表示跟链式表示。

    线性表的顺序表示和实现

    线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,这种数据结构称之为顺序表

    下面顺序表的一种实现

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 #include <stdbool.h>
      4 #define OK 1
      5 #define ERROR 0
      6 #define OVERFLOW -1 
      7 #define LIST_INIT_SIZE 100     //线性表存储空间的初始分配量 
      8 #define LISTINCREMENT 10       //线性表存储空间的分配增量  
      9 
     10 typedef char ElemType;
     11 typedef struct
     12 {
     13     ElemType *elem;     //存储空间的基址 
     14     int length;         //当前长度 
     15     int listsize;       //当前分配的存储容量(以sizeof(ElemType)为单位) 
     16 }SqList;
     17 
     18 //初始化顺序表 
     19 int InitList(SqList &L)
     20 {
     21     L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
     22     if(!L.elem)  return OVERFLOW;  //存储分配失败 
     23     L.length=0;                    //空表长度为0 
     24     L.listsize=LIST_INIT_SIZE;     //初始存储容量 
     25     return OK;
     26 }
     27 
     28 //销毁顺序表
     29 void DestroyList(SqList &L)
     30 {
     31     free(L.elem);
     32 } 
     33 
     34 //在顺序表L中第i个位置之前插入新的元素e 
     35 int ListInsert(SqList &L,int i,ElemType e)
     36 {
     37     //i的合法值为1≤i≤L.length+1 
     38     if(i<1||i>L.length+1)  return ERROR;  
     39     //当前存储空间已满,重新分配空间 
     40     if(L.length>=L.listsize)
     41     {
     42         ElemType *newbase=NULL;
     43         newbase=(ElemType *)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
     44         if(!newbase)  return OVERFLOW;
     45         L.elem=newbase;
     46         L.listsize+=LISTINCREMENT; 
     47     }
     48     //p为插入位置
     49     ElemType *p=&(L.elem[i-1]);
     50     //插入位置及之后的元素右移  q为最后一个元素的位置 
     51     for(ElemType *q=(L.elem+L.length-1);q>=p;--q)  *(q+1)=*q; 
     52     *p=e;              //插入e 
     53     ++L.length;         //表长加1 
     54 }
     55 
     56 //在顺序表L中删除第i个元素,并用e返回其值
     57 int ListDelete(SqList &L,int i,ElemType &e)
     58 {
     59     //i的合法值为1≤i≤L.length
     60     if(i<1||i>L.length)  return ERROR;
     61     ElemType *p=&(L.elem[i-1]);    //p为被删除位置元素的位置 
     62     e=*p;                          //将删除元素的值赋给e 
     63     ElemType *q=L.elem+L.length-1; //q为表尾元素的位置
     64     for(;p<=q;++p)    *p=*(p+1);
     65     --L.length;
     66     return OK; 
     67 }
     68 
     69 
     70 //判断顺序表是否为空表 
     71 bool ListEmpty(SqList &L)
     72 {
     73     return (L.length==0);
     74 } 
     75 
     76 //求顺序表的长度
     77 int ListLength(SqList &L)
     78 {
     79     return (L.length);
     80 } 
     81 
     82 //输出顺序表
     83 void DispList(SqList &L)
     84 {
     85     if(ListEmpty(L))  return;
     86     for(int i=0;i<L.length;++i)
     87         printf("%c",L.elem[i]);
     88     printf("
    ");
     89 } 
     90 
     91 //获取顺序表中索引位置的元素值
     92 bool GetElem(SqList &L,int i,ElemType &e)
     93 {
     94     if(i<1||i>L.length)  return false;
     95     e=L.elem[i-1];
     96     return true; 
     97 } 
     98 
     99 //按元素值查找
    100 int LocateElem(SqList &L,ElemType e)
    101 {
    102     int i=0;
    103     //查找元素e 
    104     while(i<L.length&&L.elem[i++]!=e);
    105     //未找到 
    106     if(i>L.length)  return -1;
    107     return i; 
    108 } 
    View Code

    线性表的链式表示和实现

    线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。

    为了表示元素之间的逻辑(先后)关系,对于任一数据元素,除了存储元素本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。

    每个数据元素包含两个域:其中存储数据元素信息的域称为数据域,存储直接后继存储位置的域称为指针域

    下面是单链表(带头节点)的一种实现

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 typedef char ElemType;
      4 //定义单链表节点类型 
      5 typedef struct LNode
      6 {
      7     ElemType data;
      8     struct LNode *next;
      9 }LinkList;
     10 
     11 //初始化 
     12 void InitList(LinkList *&L)
     13 {
     14     //创建头节点 
     15     L=(LinkList *)malloc(sizeof(LinkList));
     16     L->next=NULL;
     17 } 
     18 
     19 //销毁单链表
     20 void DestroyList(LinkList *&L)
     21 {
     22     LNode *p=L;
     23     LNode *q=p->next;
     24     while(q!=NULL)
     25     {
     26         free(p);
     27         p=q;
     28         q=q->next;
     29     }
     30     free(p);
     31 } 
     32 
     33 //判断是否为空表
     34 bool ListEmpty(LinkList *L)
     35 {
     36     return  (L->next==NULL);
     37 } 
     38 
     39 //求单链表的长度
     40 int ListLength(LinkList *L)
     41 {
     42     int i=0;
     43     LNode *p=L;
     44     while(p->next!=NULL)
     45     {
     46         i++;
     47         p=p->next;
     48     }
     49     return i;
     50 } 
     51 
     52 //输出单链表
     53 void DispList(LinkList *L)
     54 {
     55     LNode *p=L->next;
     56     while(p!=NULL)
     57     {
     58         printf("%c",p->data);
     59         p=p->next;
     60     }
     61     printf("
    ");
     62 } 
     63 
     64 //按逻辑索引值找数据元素值  该值通过e返回 
     65 bool GetElem(LinkList *L,int i,ElemType &e)
     66 {
     67     int j=0;
     68     LNode *p=L;
     69     while(j<i&&p!=NULL)
     70     {
     71         j++;
     72         p=p->next;
     73     }
     74     if(p==NULL)
     75         return false;
     76     e=p->data;
     77     return true;
     78 } 
     79 
     80 //按元素值查找逻辑索引值
     81 int LocateElem(LinkList *L,ElemType e)
     82 {
     83     LNode *p=L->next;
     84     int i=1;
     85     while(p!=NULL&&p->data!=e)
     86     {
     87         i++;
     88         p=p->next;
     89     }
     90     if(p==NULL)
     91         return 0;
     92     return i;
     93 } 
     94 
     95 //插入数据元素
     96 bool ListInsert(LinkList *&L,int i,ElemType e)
     97 {
     98     int j=0;
     99     LNode *p=L;
    100     //找到索引为i-1的节点 
    101     while(j<i-1&&p!=NULL)
    102     {
    103         j++;
    104         p=p->next;
    105     }
    106     if(p==NULL)
    107         return false;
    108     LNode *node=(LNode *)malloc(sizeof(LNode));
    109     node->data=e;
    110     node->next=p->next;
    111     p->next=node;
    112     return true; 
    113 }
    114 
    115 //删除数据元素
    116 bool ListDelete(LinkList *&L,int i,ElemType &e)
    117 {
    118     int j=0;
    119     LNode *p=L;
    120     //找到索引为i-1的节点 
    121     while(j<i-1&&p!=NULL)
    122     {
    123         j++;
    124         p=p->next;
    125     }
    126     //未找到第i-1个节点 
    127     if(p==NULL)
    128         return false;
    129     //不存在第i个节点 
    130     if(p->next==NULL)
    131         return false;
    132     //记录要删除的节点 
    133     LNode *q=p->next;
    134     e=q->data;
    135     p->next=q->next;
    136     free(q);
    137     return true;
    138 } 
    View Code

    双链表中的元素比单链表的元素多出一个指针域,这个指针域指向该元素的前驱。

    双链表的实现跟单链表类似,只是多出了对前驱指针域的操作。

    下面是双链表(带头节点)的一种实现(只给出与单链表不同的代码)

     1 #include <stdio.h>
     2 #include <malloc.h>
     3 typedef char ElemType;
     4 //定义双链表节点类型
     5 typedef struct DNode
     6 {
     7     ElemType data;
     8     struct DNode *prior;
     9     struct DNode *next;
    10 }DLinkList;
    11 
    12 //初始化
    13 void InitList(DLinkList *&L)
    14 {
    15     //创建头结点 
    16     L=(DLinkList *)malloc(sizeof(DLinkList));
    17     L->prior=L->next=NULL;
    18 } 
    19 
    20 //插入数据元素
    21 bool ListInsert(DLinkList *&L,int i,ElemType e)
    22 {
    23     int j=0;
    24     DNode *p=L;
    25     //找到索引为i-1的节点 
    26     while(j<i-1&&p!=NULL)
    27     {
    28         j++;
    29         p=p->next;
    30     }
    31     if(p==NULL)
    32         return false;
    33     //将*node插入到*p之后 
    34     DNode *node=(DNode *)malloc(sizeof(DNode));
    35     node->data=e;
    36     node->next=p->next;
    37     //如果*p不是最后一个节点 
    38     if(p->next!=NULL)
    39         p->next->prior=node;
    40     p->next=node;
    41     node->prior=p;
    42     return true; 
    43 } 
    44 
    45 //删除数据元素
    46 bool ListDelete(DLinkList *&L,int i,ElemType &e) 
    47 {
    48     int j=0;
    49     DNode *p=L;
    50     //找到索引为i-1的节点 
    51     while(j<i-1&&p!=NULL)
    52     {
    53         j++;
    54         p=p->next;
    55     }
    56     //未找到第i-1个节点 
    57     if(p==NULL)
    58         return false;
    59     //不存在第i个节点 
    60     if(p->next==NULL)
    61         return false;
    62     //删除*q节点
    63     DNode *q=p->next;
    64     e=q->data;
    65     p->next=q->next;
    66     //如果*q不是最后一个节点 
    67     if(q->next!=NULL)    
    68         q->next->prior=q->prior;
    69     free(q);
    70     return true;
    71 }
    View Code

    循环链表是另一种形式的链式存储的结构,它的特点是表中最后一个节点的指针域指向头节点,整个链表形成一个环。

    下图是一个循环单链表

    下面是循环单链表的实现,跟单链表不同的是要处理尾节点的指针域

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 typedef char ElemType;
      4 typedef struct LNode
      5 {
      6     ElemType data;
      7     struct LNode *next;
      8 }LinkList;
      9 
     10 //初始化循环链表 
     11 void InitList(LinkList *&L)
     12 {
     13     //创建头结点
     14     L=(LinkList *)malloc(sizeof(LinkList));
     15     L->next=L; 
     16 } 
     17 
     18 //销毁循环链表
     19 void DestoryList(LinkList *&L)
     20 {
     21     LNode *p=L;
     22     LNode *q=L->next;
     23     while(q!=L)
     24     {
     25         free(p);
     26         p=q;
     27         q=q->next;
     28     }
     29     free(p);
     30 } 
     31 
     32 //判断是否为空表
     33 bool ListEmpty(LinkList *L)
     34 {
     35     return (L->next==L);
     36 } 
     37 
     38 //求表长
     39 int ListLength(LinkList *L)
     40 {
     41     int i=0;
     42     LNode *p=L->next;
     43     while(p!=L)
     44     {
     45         i++;
     46         p=p->next;
     47     }
     48     return i;
     49 }
     50 
     51 //输出线性表
     52 void DispList(LinkList *L)
     53 {
     54     LNode *p=L->next;
     55     while(p!=L)
     56     {
     57         printf("%c",p->data);
     58         p=p->next;
     59     }
     60     printf("
    ");
     61 } 
     62 
     63 //找指定位置的元素
     64 bool GetElem(LinkList *L,int i,ElemType &e)
     65 {
     66     LNode *p=L->next;
     67     int j=0;
     68     while(j<i-1&&p!=L)
     69     {
     70         j++;
     71         p=p->next;
     72     }
     73     if(p==L)
     74         return false;
     75     e=p->data;
     76     return true;
     77 } 
     78 
     79 //查找元素位置
     80 int LocateElem(LinkList *L,ElemType e)
     81 {
     82     LNode *p=L->next;
     83     int i=1;
     84     while(p!=L&&p->data!=e)
     85     {
     86         i++;
     87         p=p->next;
     88     }
     89     if(p==L)
     90         return 0;
     91     return i;
     92 } 
     93 
     94 //插入元素
     95 bool ListInsert(LinkList *&L,int i,ElemType e)
     96 {
     97     LNode *p=L;
     98     int j=0;
     99     //找到索引为i-1的节点 
    100     while(p->next!=L&&j<i-1)
    101     {
    102         j++;
    103         p=p->next;
    104     }
    105     if(j!=i-1)
    106         return false;
    107     LNode *node=(LNode *)malloc(sizeof(LNode));
    108     node->data=e;
    109     //*p是最后一个元素 
    110     if(p->next==L)
    111     {
    112         p->next=node;
    113         node->next=L;
    114     }
    115     else
    116     {
    117         node->next=p->next;
    118         p->next=node;
    119     }
    120     return true;
    121 }
    122 
    123 //删除元素
    124 bool ListDelete(LinkList *&L,int i,ElemType &e)
    125 {
    126     LNode *p=L;
    127     int j=0;
    128     //找到索引为i-1的节点 
    129     while(p->next!=L&&j<i-1)
    130     {
    131         j++;
    132         p=p->next;
    133     }
    134     if(j!=i-1)
    135         return false;
    136     //如果第i-1个节点是最后一个节点 
    137     if(p->next==L)
    138         return false;
    139     LNode *q=p->next;
    140     e=q->data;
    141     //如果第i个节点是最后一个节点 
    142     if(q->next==L)
    143     {
    144         p->next=L;    
    145         free(q);
    146     }
    147     else
    148     {
    149         p->next=q->next;
    150         free(q);
    151     }
    152     return true;
    153 } 
    View Code

    下图是一个循环双链表,它的实现可以参照循环单链表跟普通双链表

  • 相关阅读:
    原生js片段
    IE 怪异模式(Quirks Mode)对 HTML 页面的影响
    CSS3 @font-face 的使用
    css面试题——九宫格
    一些前端冷知识
    利用 document.domain 在当前的域名或者基础域名 实现跨域
    JS 判断浏览器客户端类型(ipad,iphone,android)
    防止网站被iframe调用
    doctype 的各种声明
    JQUERY中的事件处理:RETURN FALSE、阻止默认行为、阻止冒泡以及兼容性问题
  • 原文地址:https://www.cnblogs.com/runnyu/p/4702415.html
Copyright © 2011-2022 走看看