• 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

  • 相关阅读:
    NW开发教程系列六:表头和表体(多表体)
    Java 正则表达式 量词 --- 三种匹配模式【贪婪型、勉强型、占有型】
    信号量与PV操作
    java的(PO,VO,TO,BO,DAO,POJO)解释
    使用Application对象简单完成网站总访问人数的统计
    更新记录后关闭子窗口并刷新父窗口的Javascript
    jquery jqPlot API 中文使用教程
    一款基于bootstrap的datetimepicker
    2013杭州赛区Ants hdu4776
    openGL中的函数调用类成员函数
  • 原文地址:https://www.cnblogs.com/zuoanfengxi/p/12512695.html
Copyright © 2020-2023  润新知