zoukankan      html  css  js  c++  java
  • 数据结构——顺序表与链表

    1.顺序表

    我在学习完顺序表后一直对顺序表、数组、结构体数组这几个概念存在一些疑问,这里给出一些分析和看法。

    顺序表:在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。

    数组:把具有相同数据类型的若干变量按有序的形式组织起来,以便于程序处理,这些数据元素的集合就是数组。

    从顺序表的定义来看,它和数组确实有很大的联系。首先,它是以数组的形式来保存的,其次,它和数组一样都是存储的元素物理地址相邻,具有很大的相似性。
    但,仔细研究还是会发现它们的不同之处:
    typedef struct Sqlist
    {
        ElemType *slist;      /*存储空间的基地址,动态分配的一维数组*/
        int length;           /*顺序表的当前长度*/
        int listsize;         /*当前分配的存储空间*/
    } Sqlist;

    顺序表是通过结构体来定义的,在结构体中有一个数组来保存顺序表所存储的数据,然后用定义的整形变量来确定数组中存储的有效数据的个数。而数组直接定义,简洁明了,很容易使用。这样看来数组比顺序表更加方便使用了。但是,数组也有它的缺陷它不能进行增,删等操作,而这些对顺序表来说就很简单了。

      1 #include<stdio.h>
      2 #include<malloc.h>
      3 #define ERROR 0
      4 #define OK 1
      5 #define INIT_SIZE 5     /*初始分配的顺序表长度*/
      6 #define INCREM 5        /*溢出时,顺序表长度的增量*/
      7 typedef  int ElemType;  /*定义表元素的类型*/
      8 typedef struct Sqlist
      9 {
     10     ElemType *slist;      /*存储空间的基地址*/
     11     int length;           /*顺序表的当前长度*/
     12     int listsize;         /*当前分配的存储空间*/
     13 } Sqlist;
     14 
     15 int InitList_sq(Sqlist *L); /*线性表的初始化*/
     16 int CreateList_sq(Sqlist *L,int n); /*  构造一个长度为n顺序表  */
     17 int ListInsert_sq(Sqlist *L,int i,ElemType e);/*在表的第i个位置前插入一个元素e */
     18 int PrintList_sq(Sqlist *L);  /*输出顺序表的元素*/
     19 int ListDelete_sq(Sqlist *L,int i); /*删除第i个元素*/
     20 int ListLocate(Sqlist *L,ElemType e); /*查找值为e的元素*/
     21 
     22 int InitList_sq(Sqlist *L)
     23 {
     24     L->slist=(ElemType*)malloc(INIT_SIZE*sizeof(ElemType));
     25     if(!L->slist)
     26     {
     27         return ERROR;
     28     }
     29     L->length=0;///空表的长度为0
     30     L->listsize=INIT_SIZE;///初始存储容量
     31     return OK;
     32 }/*InitList*/
     33 
     34 int CreateList_sq(Sqlist *L,int n)
     35 {
     36     ElemType e;
     37     int i;
     38     for(i=0; i<n; i++)
     39     {
     40         printf("input data %d",i+1);
     41         scanf("%d",&e);
     42         if(!ListInsert_sq(L,i+1,e))
     43         {
     44             return ERROR;
     45         }
     46     }
     47     return OK;
     48 }/*CreateList*/
     49 
     50 /*输出顺序表中的元素*/
     51 int PrintList_sq(Sqlist *L)
     52 {
     53     int i;
     54     for(i=1; i<=L->length; i++)
     55     {
     56         printf("%5d",L->slist[i-1]);
     57     }
     58     return OK;
     59 }/*PrintList*/
     60 
     61 int ListInsert_sq(Sqlist *L,int i,ElemType e)
     62 {
     63     int k;
     64     if(i<1||i>L->length+1)///i值不合法
     65     {
     66         return ERROR;
     67     }
     68     if(L->length>=L->listsize)///当前存储空间已满,增加分配
     69     {
     70         L->slist=(ElemType*)realloc(L->slist,(INIT_SIZE+INCREM)*sizeof(ElemType));
     71         if(!L->slist)
     72         {
     73             return ERROR;
     74         }
     75         L->listsize+=INCREM;
     76     }
     77     for(k=L->length-1; k>=i-1; k--)///元素后移
     78     {
     79         L->slist[k+1]= L->slist[k];
     80     }
     81     L->slist[i-1]=e;///在第i个位置上插入元素e
     82     L->length++;///表长加1
     83     return OK;
     84 }/*ListInsert*/
     85 
     86 /*在顺序表中删除第i个元素*/
     87 int ListDelete_sq(Sqlist *L,int i)
     88 {
     89     int p;
     90     if(i<1||i>L->length)///i值不合法
     91     {
     92         return ERROR;
     93     }
     94     for(p=i-1; p<L->length-1; p++)///元素后移
     95     {
     96         L->slist[p]=L->slist[p+1];
     97     }
     98     L->length--;///表长减1
     99     return OK;
    100 }
    101 /*在顺序表中查找指定值元素,返回其序号*/
    102 int ListLocate(Sqlist *L,ElemType e)
    103 {
    104     int i;
    105     i=0;
    106     while((i<=L->length)&&(L->slist[i]!=e))
    107     {
    108         i++;
    109     }
    110     if(i<=L->length)
    111     {
    112         return i+1;
    113     }
    114     else
    115     {
    116         return -1;
    117     }
    118 }
    119 
    120 int main()
    121 {
    122     Sqlist sl;
    123     int n,m,k;
    124     printf("please input n:");  /*输入顺序表的元素个数*/
    125     scanf("%d",&n);
    126     if(n>0)
    127     {
    128         printf("
    1-Create Sqlist:
    ");
    129         InitList_sq(&sl);
    130         CreateList_sq(&sl,n);
    131         printf("
    2-Print Sqlist:
    ");
    132         PrintList_sq(&sl);
    133         printf("
    please input insert location and data:(location,data)
    ");
    134         scanf("%d,%d",&m,&k);
    135         ListInsert_sq(&sl,m,k);
    136         printf("
    3-Print Sqlist:
    ");
    137         PrintList_sq(&sl);
    138         printf("
    ");
    139     }
    140     else
    141         printf("ERROR");
    142     return 0;
    143 }

    2.链表

    顺序表在使用的时候有以下两个主要的缺点:

    (1)插入和删除运算的时候必须移动大量(几乎一半)数据元素,效率低下。

    (2)必须预先分配存储空间,造成空间利用率低,而且表的容量很难扩充。

    为了克服顺序表的缺点,可以使用动态存储分配来存储线性表,也就是链式存储结构。

    typedef struct LNode   /*线性表的单链表存储*/
    {
        ElemType data;///数据域
        struct LNode *next;///指针域
    } LNode,*LinkList;

    在单链表中任何两个元素的存储位置之间没有固定的联系,每个元素的存储位置都包含在其直接前驱结点的信息中。

      1 #include<stdio.h>
      2 #include<malloc.h>
      3 #define ERROR 0
      4 #define OK 1
      5 typedef  int ElemType; /*定义表元素的类型*/
      6 typedef struct LNode   /*线性表的单链表存储*/
      7 {
      8     ElemType data;///数据域
      9     struct LNode *next;///指针域
     10 } LNode,*LinkList;
     11 
     12 LinkList CreateList(int n); /*构造长度为n的链表*/
     13 void PrintList(LinkList L); /*输出带头结点单链表的所有元素*/
     14 int GetElem(LinkList L,int i,ElemType *e); /* 在第i个元素存在的情况下,替换为e*/
     15 
     16 LinkList CreateList(int n)
     17 {
     18     LNode *p,*q,*head;
     19     int i;
     20     head=(LinkList)malloc(sizeof(LNode));
     21     head->next=NULL;///头结点
     22     p=head;
     23     for(i=0; i<n; i++)
     24     {
     25         q=(LinkList)malloc(sizeof(LNode));
     26         printf("input data %i:",i+1);
     27         scanf("%d",&q->data);            /*输入元素值*/
     28         q->next=NULL;                    /*结点指针域置空*/
     29         p->next=q;                       /*新结点连在表末尾*/
     30         p=q;
     31     }
     32     return head;
     33 }/*CreateList*/
     34 
     35 void PrintList(LinkList L)///输出链表存储内容
     36 {
     37     LNode *p;
     38     p=L->next;  /*p指向单链表的第1个元素*/
     39     while(p!=NULL)
     40     {
     41         printf("%5d",p->data);
     42         p=p->next;
     43     }
     44 }/*PrintList*/
     45 
     46 int GetElem(LinkList L,int i,ElemType *e)///获取链表第i位置上的元素
     47 {
     48     LNode *p;
     49     int j=1;
     50     p=L->next;///指向第一个节点
     51     while(p&&j<i)///向后查找,直到p指向第i个元素或者p为空
     52     {
     53         p=p->next;
     54         j++;
     55     }
     56     if(!p||j>i)///第i个元素不存在
     57     {
     58         return ERROR;
     59     }
     60     *e=p->data;///获取到第i个元素
     61     return OK;
     62 }/*GetElem*/
     63 
     64 int ListInsert_sq(LinkList L,int i,ElemType e)///向链表中第i个位置前插入元素
     65 {
     66     int j=0;
     67     LinkList p=L,s;
     68     while(p&&j<i-1)///向后查找寻找第i-1个元素
     69     {
     70         p=p->next;
     71         j++;
     72     }
     73     if(!p||j>i-1)
     74     {
     75         return ERROR;
     76     }
     77     s=(LinkList)malloc(sizeof(struct LNode));///生成新结点
     78     s->data=e;///插入
     79     s->next=p->next;
     80     p->next=s;
     81     return OK;
     82 }
     83 int ListDelete(LinkList L,int i,ElemType *e)///删除链表第i个位置上的元素,并由e返回其值
     84 {
     85     int j=0;
     86     LinkList p=L,q;///p初始化时指向头结点
     87     while(p->next&&j<i-1)///向后寻找第i个结点,并令p指向其前驱
     88     {
     89         p=p->next;
     90         j++;
     91     }
     92     if(!(p->next)||j>i-1)
     93     {
     94         return ERROR;
     95     }
     96     q=p->next;///q指向被删除结点
     97     p->next=q->next;
     98     *e=q->data;
     99     free(q);
    100     return OK;
    101 }
    102 int main()
    103 {
    104     int n,i;
    105     ElemType e;
    106     LinkList L=NULL;            /*定义指向单链表的指针*/
    107     printf("please input n:");  /*输入单链表的元素个数*/
    108     scanf("%d",&n);
    109     if(n>0)
    110     {
    111         printf("
    1-Create LinkList:
    ");
    112         L=CreateList(n);
    113         printf("
    2-Print LinkList:
    ");
    114         PrintList(L);
    115         printf("
    3-GetElem from LinkList:
    ");
    116         printf("input i=");
    117         scanf("%d",&i);
    118         if(GetElem(L,i,&e))
    119             printf("No%i is %d",i,e);
    120         else
    121             printf("not exists");
    122     }
    123     else
    124         printf("ERROR");
    125     return 0;
    126 }
  • 相关阅读:
    const 函数
    为什么要进行初始化(C语言)
    关于矩阵的逆
    在写论文的参考文献时,有的段落空格很大,有的段落则正常,原因及解决方法(wps)
    C#递归搜索指定目录下的文件或目录
    try catch finally 执行顺序面试题总结
    关于try catch finally的执行顺序解释 都有return
    C# 序列号和反序列化 对象写入bin
    C# 序列化和反序列化 详解 对象和XML文件之间
    在C#中,Json的序列化和反序列化的几种方式总结
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/9883872.html
Copyright © 2011-2022 走看看