顺序表是最简单最自然的存储方法,它是将顺序表中的结点按逻辑顺序依次存放在一组地址连续的存储单元中,也就是说,顺序表的逻辑顺序与物理顺序是一致的。一般情况下,顺序表中的所有结点的类型是相同的,也就是说每个结点所占的空间是相同的。设结点所占的空间大小为L,如果顺序表中有n个结点(顺序表的长度为n),则顺序表所占空间大小为n*L。但是由于顺序表中的结点数是不确定的,其内存空间也不确定,因此可事先分配一个足够的maxL个连续内存空间,使其能存储max个结点。在C语言中,可用一位数组及结构体类型定义顺序表。
顺序表的基本运算,这里只讨论插入和删除两个基本运算。
程序分析:
#include <stdio.h> #include <stdlib.h> #include <conio.h> #define Maxsize 1024 //顺序表中可能的最大节点数 typedef int datatype; //结点类型为datatype,这里datatype为int型 //则结点所占空间大小L为四个字节 //这里用结构体定义 typedef struct { datatype data[Maxsize]; int last; //线性表中最后一个结点的下标值,即线性表的长度n=last+1; }sequenlist; int Insert(sequenlist *L,datatype x,int i) { int j; if(L->last>=Maxsize-1) { printf("空间溢出!"); return 0; } else if(i<1||i>L->last+2) { printf("插入位置非法!"); return 0; } else { for(j=L->last;j>=i-1;j--) { L->data[j+1]=L->data[j];//数据后移 } L->data[i-1]=x; L->last=L->last+1; } return 1; } int Delete(sequenlist *L,int i) { int j; if(i<1||i>L->last+1) { printf("删除位置非法!"); return 0; } else { for(j=i;j<=L->last;j++) { L->data[j-1]=L->data[j];//数据前移 } L->last=L->last-1; } return 1; } int main(void) { sequenlist *L; int i,ch,n; while(1) { printf("\n\t请选择\n"); printf("\t1.输入线性表\n"); printf("\t2.插入线性表\n"); printf("\t3.删除线性表\n"); printf("\t4.退出\n"); ch=getch(); switch(ch) { case '1': printf("\n请输入线性表中数据个数n=");//输入数据 scanf("%d",&n); printf("\n"); L=(sequenlist *)malloc(sizeof(sequenlist)); for(i=0;i<n;i++) { printf("请输入第%d个数据值:",i+1); scanf("%d",&L->data[i]); } L->last=n-1; printf("\n输入的线性表数据为:\n"); for(i=0;i<=L->last;i++) { printf("%d ",L->data[i]); } printf("\n"); break; case '2': printf("\n输入要插入的数据;"); scanf("%d",&n); printf("\n输入要插入的位置"); scanf("%d",&i); printf("\n"); if(Insert(L,n,i)) { printf("\n插入后的数据:");//输出插入后的数据 for(i=0;i<=L->last;i++) { printf("%d ",L->data[i]); } printf("\n"); } break; case '3': printf("\n输入要删除数据的位置;");//删除数据 scanf("%d",&i); printf("\n"); if(Delete(L,i)) { printf("\n删除后的数据顺序表:");//输出删除后的数据 for(i=0;i<=L->last;i++) { printf("%d ",L->data[i]); } printf("\n"); break; case '4':return 0; } } } }
顺序表特点:
1)存储结构的顺序与逻辑结构的顺序完全一致,因此顺序表的最大优点是可以方便地随机存取表中任一个结点,但它的缺点也非常明显;
2)插入或删除运算不方便,除表尾的位置以外,其他位置上的操作都要移动大量的结点,平均时间复杂度O(n),其效率较低。
3)由于顺序表所占空间必须是连续空间,而结点数并不固定,只能预先分配空间(静态分配)。因此,难以确定合适的存储空间,空间过大浪费资源,空间过小造成溢出。为了克服顺序表的缺点,下节会介绍链表。