1_线性表之顺序存储
逻辑结构
具有相同数据类型的n个数据元素的有序,有限集。
1.集合中必存唯一 第一元素 和 最后元素
2.除 第一元素 和 最后元素外,均有唯一前驱和后继。
存储结构
用一组地址连续的存储单元以此存放线性表中的数据元素。
LOC(ai)= LOC(ai-1) + sizeof
LOC(ai)= LOC(a1) +(i-1)×sizeof
*sizeof是每个数据元素所占存储空间大小
*线性表中元素位序从一开始,数组从0开始
表示方法
静态
1 #define MaxSize 50 //最大长度 2 typedef struct{ 3 ElemType data[MaxSize]; //数据元素 4 int length; //当前长度 5 }SqList //顺序表类型
动态
1 #define InitSize 50 //初始长度 2 typedef struct{ 3 ElemType *data; //动态分配地址的指针 4 int length,MaxSize; //当前长度和最大容量 5 }SqList //顺序表类型
初始动态分配语句
L.data=(elemsize*)malloc(sizeof(elemtype)*InitSize) //其中elemtype均为类型,sizeof为一个所占空间,InitSize为初始长度
基本操作1:插入
1 bool ListInsert(SqList &L,int i,Elemtype e){ 2 if (i<1 || i>L.length+1) 3 return false; 4 if(L.length>=MaxSize) 5 return false; 6 for(int j = L.length;j>=i;j--) //将i及之后元素后移 7 L.data[j] = L.data[j-1]; //j是长度,而数组从0开始,比下表多1 8 L.data[i-1] = e; 9 L.length++; 10 return true;}
基本操作2:删除
删除第i个元素,成功返回true,并把被删元素用e返回,否则返回false
1 bool ListDelete(SqList &L;int i;int &e){ 2 if(i<1||i>L.length) 3 return false; 4 e = L.data[i-1]; //第i个元素的数组下标就是i-1 5 for(int j=i;j<L.length;j++) //i之后元素前移 6 L.data[j-1]=L.data[j]; 7 L.length--; 8 return true;}
基本操作3:按值查找(顺序查找)
查找第一个值等于e的元素,并返回其位序,否则返回false
1 int LocateElem(SqList L,ElemType e){ 2 for(int i=0;i<L.length;i++) 3 if(L.data[i]==e) 4 return i+1; //下标为i,位序为i+1 5 else 6 return false;}
应用1:合并
将两个有序顺序表合成一个新的有序顺序表,由函数返回
1 bool Merge(SeqList L1,SeqList L2,SeqList &C){ 2 if(L1.length+L2.length>C.length) 3 return false; 4 int i=0,j=0,k=0; 5 while(i<A.length&&j<B.length){ //循环两两比较,小者存入结果表 6 if(A.data[i]<=B.data[j]) 7 C.data[k++]=A.data[i++]; 8 else 9 B.data[k++]=A.data[j++] } 10 while(i<A..length) //将比完还剩的部分接上 11 C.data[k++]=A.data[i++] 12 while(j<B..length) 13 C.data[k++]=B.data[j++] 14 C.length=k 15 return true; }
*while与.data[i++]的结合甚妙
应用2:逆置
在空间复杂度为O(l)的前提下,将顺序表所有元素逆置
1 void Reverse(SqList &L){ 2 ElemType temp; 3 for(int i=0;i<L.length/2;i++) //若是奇长度就是把中间长度赋给本身 4 temp=L.data[i]; //由此开始用建好的辅助变量交换位置 5 L.data[i]==L.data[L.length-i-1]; //因为起始下标0,最后元素下标 length-1 6 L.data[L.length-i-1]=temp; }
应用3:顺序表位置交换
编写函数,将A[m+n]中存放的两个顺序表位置互换
实现步骤:先把A中全部元素逆置,再分别把对前n个和后m个元素逆置,得到结果。
void Reverse(DataType A[],int left,int right,int ArraySize){ if(left>=right||right>=ArraySize) return; int mid=(left+right)/2; //界线 for(int i=0;i<=mid-left;i++){ DataType temp=A[left+i]; //开始借助辅助变量互换循环 A[left+i]=A[right-i]; A[right-i]=temp; }} void Exchange(DataType A[],int m,int n,int ArraySize) Reverse(A,0,m+n-1,ArraySize); Reverse(A,0,n-1,ArraySize); Reverse(A,n,m+n-1,ArraySize);
应用4:删除最值
删除顺序表中最小值元素(假设唯一),并返回其值,空出的位置由最后一个元素填补,若表空返回错误信息
实现步骤:查找元素的值和位置这两个关键点。
bool Del_Min(SqList &L,ElemType &value) { if(L.length==0) return false; value=L.data[0]; //假定第一个元素最小 int pos=0; for(int i=1;i<L.length;i++) //循环记录具有最小值元素的值和位序 if(L.data[i]<value){ value=L.data[i]; pos=i; } L.data[pos]= L.data[L.length-1]; L.length--; return true; }
应用5:删除某值
前提时间复杂度为O(n),空间复杂度为O(l)
解法一:用动态k从头筛选留下的
void del_x_1(SqList &L,ElemType x){ int k=0; for(int i=0;i<L.length;i++) if(L.data[i]!=x){ L.data[k]=L.data[i]; k++; } L.length=k; }
解法二:分支一K记录步数,分支二留下按步数向前覆盖
void del_x_2(SqList &L,ElemType x){ int k=0; while(i<L.length){ if(L.data[i]==x) k++; else L.data[i-k]=L.data[i]; //当前元素前移k位覆盖 i++; } L.length=L.length-k; }
应用6:整块移动
删除有序顺序表中值属于[s,t]区间的数
bool Del_st_(SqList &L,ElemType t,ElemType s){ int i,j; if(s>=t||L.length==0) return false; for(i=0;i<L.length&&L.data[i]<s;i++) //寻找>=s的第一个元素 if(i>=L.length) return false; for(j=i;j<L.length&&L.data[j]<t;j++) ///寻找>=t的第一个元素 for(;j<L.length;i++,j++) //前移填补被删块 L.data[i]=L.data[j]; L.length=i; return true; }
*用for空执行语句找pos
应用7:删除重复值
删除有序表中重复值
实现步骤:初试看成非重复有序表,之后依次判断后面的元素是否与前面非重复有序表的最后一个元素相同,若相同则继续向后判断,若不同则插入到前面非重复有序表的最后,直到判断到表尾。
bool Del_Same(SqList &L) { if(L.length==0) return false; int i,j; //i存储第一个不同的元素,j工作指针 for(i=0,j=1;j<L.length;j++) if(L.data[i]!=L.data[j]) //查找下一个与不重复表最后数不同的元素 L.data[++i]=L.data[j] //找到后接上 L.length=i+1; }
for与while的几种灵活用法
(int i=? int j=?; ; i++,j++)
for() [k++]
while() [i++] [j++]