顺序存储结构

  定义:一段地址连续的储存单元依次存储的数据元素。

    实际上就是把数组封装进结构体,增加一个记录当前长度的变量。

  时间复杂度存储,查看,时间复杂度为 O(1)

        删除,插入,时间复杂度为 O(n)

优点:无需为表示表中元素之间的逻辑关系而添加额外的存储空间

    可以快速的存,取表中的任意位置的元素

缺点:插入和删除操作需要移动大量的元素

    当线性表的长度变化较大时,难以确定存储空间的容量

    容易造成存储空间的碎片

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 #define MAXSIZE 20
  4 typedef int ElemType;
  5 
  6 typedef struct SQList{
  7     ElemType data[MAXSIZE];//对数组进行封装
  8     int length;//当前长度
  9 }List,* PList;
 10 
 11 void printList(PList);
 12 void insert(PList);
 13 void add(PList);
 14 void del(PList);
 15 void delAll(PList);
 16 
 17 void delAll(PList pL){
 18     pL->length=0;
 19 }
 20 
 21 void del(PList pL){
 22     int i=0;
 23     printf("请输入要删除的元素位置:");
 24     scanf("%d",&i);
 25     if(i>0 && i<=pL->length){
 26         i--;
 27         while(i<pL->length){
 28             pL->data[i]=pL->data[i+1];
 29             i++;
 30         }
 31         pL->length--;
 32     }else
 33         printf("删除的位置错误!");
 34 }
 35 
 36 void printList(PList pL){
 37     int i=0;
 38     while(i<pL->length){
 39         printf("%d   ",pL->data[i]);
 40         i++;
 41     }
 42     printf("\n");
 43 }
 44 
 45 void insert(PList pL){
 46     int n=0,i=0;
 47     ElemType val;
 48     printf("请输入要插入的整数值(-1结束):");
 49     scanf("%d",&val);
 50     printf("请输入要插入的位置:");
 51     scanf("%d",&i);
 52     while(val != -1){
 53         if(pL->length+1 < MAXSIZE){
 54             if(i>0 && i<=pL->length){
 55                 for(n=pL->length ; n>=i ; n--){
 56                     pL->data[n]=pL->data[n-1];
 57                 }
 58                 pL->data[n]=val;
 59                 pL->length++;
 60             }else
 61                 printf("插入位置有误!\n");
 62         }else{
 63             printf("线性表已满,无法插入!\n");
 64             break;
 65         }
 66         printf("请输入要插入的整数值(-1结束):");
 67         scanf("%d",&val);
 68         if(val == -1)
 69             break;
 70         printf("请输入要插入的位置:");
 71         scanf("%d",&i);
 72     }
 73 }
 74 
 75 void add(PList pL){
 76     ElemType val;
 77     printf("请输入要添加的整数值(-1结束):");
 78     scanf("%d",&val);
 79     while(val != -1){
 80         if(pL->length < MAXSIZE){
 81             pL->data[pL->length]=val;
 82             pL->length++;
 83         }else{
 84             printf("线性表已满,无法添加!\n");
 85             break;
 86         }
 87         printf("请输入要添加的整数值(-1结束):");
 88         scanf("%d",&val);
 89     }
 90 }
 91 
 92 void main(){
 93     int val=0;
 94     int i=0;
 95     PList pL=(struct SQList *)malloc(sizeof(struct SQList));
 96     pL->length=0;
 97     
 98     add(pL);
 99     printList(pL);
100 
101     insert(pL);
102     printList(pL);
103 
104     del(pL);
105     printList(pL);
106 
107     delAll(pL);
108     printList(pL);
109 }

链式存储结构

  定义:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以在内存中未被占用的任意位置

  链式存储结构:除了要存储数据元素信息(数据域),还要存储他后继元素的存储地址(指针域)——指针。

    链表中第一个结点的存储位置叫头指针,最后一个结点的指针为空(null);

头指针与头结点的异同

  头指针:

    头指针是指链表指向第一个结点的指针,若链表有头结点,则是指向头结点的指针

    头指针具有标识作用,所以常用头指针冠以链表的名字

    无论链表是否为空,头指针均不为空;头指针是链表的必要元素

  头结点:

    为了操作的统一和方便而设立,放在第一个元素的结点之前,其数据域一般无意义(也可以用来存放链表的长度)

    有了头结点,对第一个元素结点前插入结点和删除第一个结点的操作与其他结点的操作即可统一

    头结点不是链表的必要元素

  1 #include <stdio.h>
  2 #include <malloc.h>
  3 typedef int ElemType;
  4 
  5 typedef struct Node{
  6     ElemType data;//数据域        这里的数据为整性,所以可以用记录链表长度
  7     struct Node *Next;//指针域
  8 }* LinkList;
  9 
 10 LinkList initList();
 11 void add(LinkList);
 12 void printList(LinkList);
 13 void insert(LinkList);
 14 void del(LinkList);
 15 void delAll(LinkList);
 16 
 17 void delAll(LinkList pL){
 18     LinkList p,q=pL->Next;
 19     while(q != NULL){
 20         p=q;
 21         q=q->Next;
 22         free(p);
 23     }
 24     pL->Next=NULL;
 25 }
 26 
 27 void del(LinkList pL){
 28     LinkList p,q=pL;
 29     int i;
 30     printf("请输入删除位置:");
 31     scanf("%d",&i);
 32     if(i>0 && i<=pL->data){
 33         while(i>1){
 34             q=q->Next;
 35             i--;
 36         }
 37         p=q->Next;
 38         q->Next=q->Next->Next;
 39         free(p);
 40     }else
 41         printf("删除位置有误!\n");
 42 }
 43 
 44 void insert(LinkList pL){
 45     LinkList p,q=pL;
 46     int i;
 47     ElemType val;
 48     printf("请输入插入的值(-1接收):");
 49     scanf("%d",&val);
 50     printf("请输入插入位置:");
 51     scanf("%d",&i);
 52     if(i>0 && i<=pL->data){
 53         while(i>1){
 54             q=q->Next;
 55             i--;
 56         }
 57         p=(LinkList)malloc(sizeof(struct Node));
 58         p->data = val;
 59         p->Next = q->Next;
 60         q->Next=p;
 61     }else
 62         printf("插入位置有误!\n");
 63 }
 64 
 65 void printList(LinkList pL){
 66     LinkList p=pL->Next;
 67     while(p != NULL){
 68         printf("%d   ",p->data);
 69         p=p->Next;
 70     }
 71     printf("\n");
 72 }
 73 
 74 void add(LinkList pL){
 75     ElemType val;
 76     LinkList p;
 77     printf("请输入要插入的值(-1结束):");
 78     scanf("%d",&val);
 79     while(val != -1){
 80         p=(struct Node *)malloc(sizeof(struct Node));
 81         p->data=val;
 82         p->Next=pL->Next;
 83         pL->Next=p;
 84         pL->data++;
 85         printf("请输入要插入的值(-1结束):");
 86         scanf("%d",&val);
 87     }
 88 }
 89 
 90 LinkList initList(){
 91     LinkList pL=(struct Node *)malloc(sizeof(struct Node));
 92     pL->data=0;
 93     pL->Next=NULL;
 94     return pL;
 95 }
 96 
 97 void main(){
 98     LinkList pL=initList();
 99 
100     add(pL);
101     printList(pL);
102 
103     insert(pL);
104     printList(pL);
105 
106     del(pL);
107     printList(pL);
108 
109     delAll(pL);
110     printList(pL);
111 }

效率:

  单链表:无论是插入还是删除,他们都有两部分组成(查找,插入/删除);时间复杂度都是 O(n)

  顺序存储:每一次插入/删除都需要移动 [ n-1 ] 个位置,时间复杂度是 O(n)

  所以,插入/删除多个元素时,单链表的效率比顺序存储高。