1.1顺序表

0x00001:顺序表概念

顺序存储表示:将数据元素按其"逻辑先后次序"存放在一组地址连续的存储单元

顺序表:采用了顺序存储结构的线性表,这里可能有些绕

正如上面的图:比如A[0】与A[1]逻辑上相邻,相应的物理位置相邻,因此可以用“物理位置相邻”代表线性表数据元素的逻辑关系

随机存取结构:存数和取数的时候是随机的,不需要顺序遍历或搜索,而是直达。即可在相同时间内()求出任意数据元素的存储地址(存储地址是i的线性函数):LOC(Ai)=LOC(A1)+(i-1)d(每个元素占据d个存取单位比如int ,d=4)

0x00002:顺序表操作

在思考操作之前,先采用"结构体"定义顺序表,为什么用结构体呢?试想这样一个场景,在我们核对学生成绩表("那张纸"可能有空白未填的表格,"当前总格数","实际所用格数"),我们用"食指"定位某一学生的"相关信息"。

typedef struct{
ElemType * data;  //"食指"的相对定位作用,这里的ElemType是广义的,具体代表一些数据类型,data作为首地址      //                                                                                  LOC(A1)
 int     length;   //"实际所用格数"
 int     size;   //"当前总格数",形容数据的总容量
} Sqlist;  //Sqlist就是这样一种结构体类型,在这里可以理解为"那张纸(表)的样式",也就是顺序表

初始化(链表的一种)顺序表


int initList(Sqlist *L, int size){
	L->data = (int *)malloc(sizeof(int)*size);//动态分配的首地址
	if(!L->data) return 0;//一般地址非0,若为0,则返回0作为initList的返回值
	L->length = 0;       //初始化成功 
	L->size = size;
	return 1;
}  //只有一个return 值,这样的初始化相当于打印一张"怎样的空表",规定了现有行(size),L就相当于"那张纸"

销毁顺序表

void destoryList(Sqlist *L){
	free(L->data);  //free(L->data)是收回存储空间
	L->data = NULL;//指针指向一个空
	L->length = 0;
	L->size = 0;
}        //此时相当于一张白纸,没有表格,自然无法填充数据

清空顺序表

void clearList(Sqlist *L){
	L->length = 0;//只令length为零,下图中并不是十分准确,格子中可能还有数据,但由于指向了开头,原                      
                 }       //有数据会被替代,所以就是"空表"(空表看的是有效数据长度为0),或说原有数据无                                                效
Status ListClear(Sqlist *L)//线性表的清空  //第二种写法 Status是状态码
{
    int i;
    for (i = 0; i < L->cur_length; i++)
        L->data[i] = 0;          //归零操作,其实归不归0都可,其实没不要处理无效数据
    L->cur_length = 0;
    return OK;
}
//清空顺序表与销毁顺序表的区别:销毁顺序表需要再次初始化顺序表,但是清空顺序表则不用初始化顺序表。

求表长(元素个数)

int listLength(Sqlist L){      //如是SqList * L      对应L->length
	return L.length;
}

取值操作

int getElem(SqList L, int i, int *e){
	if(i >= 0 && i < L.length){ //判断合法性,用变量i
		*e = L.data[i];          //允许取值,采用指针更灵活,比如int*p=&a; p做为媒介改变a
		return 1;
	}else{
		return 0;
	}
}

定位操作

int searchElem(Sqlist L, int e){
	int i;
	for(i = 0; i < L.length; i++){
		if(e == L.data[i]) return i;
	}
	return 0;
}
算法二:
int LOCElem (Sqlist L,int e){
i=1;
p=L.data   //p是LOC(A1)的地址
while((i<L.length)&&(*p++!=e))i++;  //*p++ 先*p ,后p++
if (i<=L.length)  return i;
else   return 0;      
}         

时间复杂度分析:定位成功时,i++次数最少是0,最多n-1,(0+n-1)*n/2 *(1/n)=n-1/2 (简记就是最大最小的一半),定位不成功为n  ,故为O(n).

插入操作

先介绍动态数组扩容的函数


void Increment(Sqlist * L)
{ Sqlist  * p;
  int i;
 p->data=(int *)malloc(sizeof(int)*(size+addsize);//之前宏定义好size ,addsize
 if(!p->data) return 0;
for (i=1;i<=L->lenth;i++)
 p->data[i-1]=L->data[i-1];   //换容器 数据从L->data到p->data
  free(L->data);  //释放空间
  L->data=p->data; //移交首地址
  L->size+=addsize; //容量增加
}
int insertElem(Sqlist *L, int i, int e){ //i与位置差1
        if (i<0||i>L->length-1) //非法插入
          return 0;
	if(L->length == L->size)//顺序表已满 
		Increment(L); //扩容 在这里L是地址
       
	if(i >= 0 && i <= L->length){ //合法插入
		int j;
		for(j = L->length - 1; j >= i; j--){  // 0 1 2 ... i-1,i,...j,j+1....size
			//插入第一个元素时候不用移动其他元素           L->length-1
			if(j >= 0) 
				L->data[j+1] = L->data[j];//直至i-1个元素给了后一个
		}
		L->data[i] = e;	//插入元素 //0 1 2...i-1(e)......
		L->length++;	//长度加1 
		
}	

删除操作


int deleteElem(SqList *L, int i, int *e){  //灵活性考虑int * e;
	if(isEmpty(*L)){
		return 0;
	}  //判断是否为空表
	else{  
		if(i >= 0 && i <= L->length){  //判断合理性
			if(i!=L->length)
                       {*e = L->data[i];
			int j;
			for(j = i; j < L->length - 1; j++){
				L->data[j] = L->data[j+1];
			}
                        }
                        
			L->length--;//有效长度减一
			return 1;
		}
                      else{
			return 0;//错误标识
		}		
	}
}

输出操作

void Printlist(Sqlist *L)
{if(isEmpty(*L)){
		return 0;
	}  //判断是否为空表
else
  {
  int i=1;
  Elemtype *p=L->data;  //数组首地址
  for(i=1;i<=length-1;i++)
    printf("%d",*p++);//逐次打印

   }

}

参考:
https://www.cnblogs.com/huster666/p/5625804.html
https://zhuanlan.zhihu.com/p/36429436

posted @ 2020-03-17 21:26  zer0_1s  阅读(305)  评论(0编辑  收藏  举报