上一篇讲了线性表的定义与初始化,接下来需要了解一下线性表的一些基本操作。
查找
查找线性表是最基本的操作之一,比如根据序号查找元素的值,或者根据值查找该值是否在线性表中,如果在,那么序号是几等等。
我们来看下面一段代码:01 #define OK 1 02 #define ERROR 0 03 #define TRUE 1 04 #define FALSE 0 05 typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 06 07 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */ 08 /* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */ 09 Status GetElem(SqList L,int i,ElemType *e) 10 { 11 if(L.length==0 || i<1 || i>L.length) 12 return ERROR; 13 *e=L.data[i-1]; 14 15 return OK; 16 }
以上代码就是用来获得某一元素的操作。
插入
有了以上的基础,我们就能对顺序存储结构的插入与删除做一个讲解了。首先,我们来了解下插入操作。
- 如果插入的位置不合理,那么就抛出异常。
- 如果线性表长度大于等于数组长度,则抛出异常或者动态增加容量。
- 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置。
- 将要插入的元素填入位置i处。
- 表长加1。
01 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */ 02 /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */ 03 Status ListInsert(SqList *L,int i,ElemType e) 04 { 05 int k; 06 if (L->length==MAXSIZE) /* 顺序线性表已经满 */ 07 return ERROR; 08 if (i<1 || i>L->length+1)/* 当i比第一位置小或者比最后一位置后一位置还要大时 */ 09 return ERROR; 10 11 if (i<=L->length) /* 若插入数据位置不在表尾 */ 12 { 13 for(k=L->length-1;k>=i-1;k--) /* 将要插入位置之后的数据元素向后移动一位 */ 14 L->data[k+1]=L->data[k]; 15 } 16 L->data[i-1]=e; /* 将新元素插入 */ 17 L->length++; 18 19 return OK; 20 }
它是先往后挪一个位置,然后最后再插入进去。
删除
然后,我们一起看看删除操作。还是从思路开始说:
- 如果删除位置不合理,抛出异常
- 取出删除元素
- 从删除元素位置开始遍历到最后一个元素位置,分别将它们向前移动一个位置
- 表长减1.
01 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */ 02 /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */ 03 Status ListDelete(SqList *L,int i,ElemType *e) 04 { 05 int k; 06 if (L->length==0) /* 线性表为空 */ 07 return ERROR; 08 if (i<1 || i>L->length) /* 删除位置不正确 */ 09 return ERROR; 10 *e=L->data[i-1]; 11 if (i<l->length) /* 如果删除不是最后位置 */ 12 { 13 for(k=i;k<l->length;k++)/* 将删除位置后继元素前移 */ 14 L->data[k-1]=L->data[k]; 15 } 16 L->length--; 17 return OK; 18 } 19 </l-></l->
它是先把那个位置上的数提出来,然后向前挪。-
分析上述插入和删除两段代码和更早的获取元素代码,我们可以发现,线性表的顺序存储结构,在存/读数据时,不管是哪个位置,时间复杂度O(1),而插入或删除时,时间复杂度都是O(n)。
说完了顺序存储结构,我们可以总结下它的优缺点了,喜欢先听优点还是先听缺点呢?
好吧,从优点开始说。当我们在使用线性表的时候,我们不需要为表中元素之间的逻辑关系而增加额外的存储空间,而且可以快速的存取表中任意位置的元素。接下来谈谈缺点。如我们所见,如果我们要插入或者删除的元素是在第一个位置,那么无疑的,我们需要移动大量的元素来完成这样的操作,而且限于线性表长度必须小于数组长度,如果我们需要插入大量数据,那么很难保证空间是否充足,而如果我们要删除大量数据的时候,无疑又会造成空间的浪费。
001 #include <stdio.h> 002 #include <stdlib.h> 003 #include <time.h> 004 005 #define MAXSIZE 20 /* 存储空间初始分配量 */ 006 typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */ 007 typedef struct 008 { 009 ElemType data[MAXSIZE]; /* 数组,存储数据元素,最大值为MAXSIZE */ 010 int length; /* 线性表当前长度 */ 011 }SqList; 012 013 //顺序表的初始化 014 SqList Init() 015 { //构造一个空的线性表L,时间复杂度O(1) 016 SqList L; //定义一个顺序表 017 L.length = 0; //顺序表的长度为0 018 return L; //返回空顺序表 019 } 020 021 //顺序表的建立 022 SqList Create(SqList L) 023 { 024 int i; 025 srand((unsigned)time(NULL)); 026 for(i=0; i < 10; i++) 027 { 028 L.data[i] = rand()%100; 029 L.length++; 030 } 031 return L; 032 } 033 034 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */ 035 /* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */ 036 ElemType GetElem(SqList L,int i) 037 {// 038 if(i < 1 || i > L.length) 039 { 040 printf("查找位置错误! ");//检查查询位置是否合法 041 return 0; 042 } 043 else 044 return L.data[i-1]; 045 } 046 047 //顺序表的插入 048 SqList SqListInsert(SqList L, int i, ElemType x) 049 { //在顺序表中的第i个位置插入元素x 050 if(L.length == MAXSIZE) 051 printf("表已经满了 ");//插入时,必须检查表是否已经满了。否则会出现溢出错误 052 else if(i < 1 || i > L.length) 053 printf("插入位置错误 ");//判断插入位置的有效性 054 055 int j; 056 for(j = L.length-1; j >= i - 1; j--)//第i个位置元素逐个后移 057 L.data[j+1] = L.data[j]; 058 L.data[i-1] = x; //插入元素x 059 L.length++; //顺序表长度增1 060 return L; 061 } 062 063 SqList SqListDelete(SqList L,int i) 064 {//删除顺序表中的第i个位置的元素 065 if(i < 1 || i > L.length) 066 printf("删除位置错误 "); //检查删除位置是否合法 067 int j; 068 for(j = i-1; j < L.length; j++) 069 L.data[j] = L.data[j+1]; //将第i个位置之后的元素前移 070 071 L.length--; //顺序表长度-1 072 return L; 073 } 074 075 int main() 076 { 077 SqList nmList; 078 nmList = Init(); 079 nmList = Create(nmList); 080 int find; 081 int found; 082 int pos; 083 ElemType value; 084 char opp; 085 086 int i; 087 printf("顺序表初始化为:"); 088 for(i=0; i < nmList.length; i++) 089 { 090 printf("%d ", nmList.data[i]); 091 } 092 093 printf(" 1.查看顺序表 2.查找 3.插入 4.删除 0.退出 请选择你的操作: "); 094 while(opp != '0'){ 095 scanf("%c",&opp); 096 //printf(" 1.查找 2.插入 3.排序 0.退出 请选择你的操作: "); 097 switch(opp){ 098 case '1': 099 printf(" 查看顺序表:"); 100 for(i=0; i < nmList.length; i++) 101 { 102 printf("%d ", nmList.data[i]); 103 } 104 printf(" "); 105 break; 106 case '2': 107 printf(" 进入查找功能,请问需要查找第几个元素:"); 108 scanf("%d",&find); 109 printf("%d",find); 110 found = GetElem(nmList, find); 111 printf("第%d个值为%d ", find, found); 112 printf(" "); 113 break; 114 case '3': 115 printf("进入插入功能,请输入插入元素位置:"); 116 scanf("%d",&pos); 117 printf("请输入插入元素的值:"); 118 scanf("%d",&value); 119 nmList = SqListInsert(nmList,pos,value); 120 121 printf(" 插入元素后顺序表为:"); 122 for(i=0; i < nmList.length; i++) 123 { 124 printf("%d ", nmList.data[i]); 125 } 126 printf(" "); 127 break; 128 case '4': 129 printf("进入删除功能,请输入删除元素位置:"); 130 scanf("%d",&pos); 131 nmList = SqListDelete(nmList,pos); 132 133 printf(" 删除元素后顺序表为:"); 134 for(i=0; i < nmList.length; i++) 135 { 136 printf("%d ", nmList.data[i]); 137 } 138 printf(" "); 139 break; 140 case '0': 141 exit(0); 142 } 143 } 144 145 }