线性表(1)

 

1. 线性表的基本概念
 
数据结构分线性结构和非线性结构。线性的数据结构包括线性表、栈、队列、数组和串。
线性结构特点:在数据元素的非空有限集中
存在唯一的一个被称作“第一个”的数据元素
存在唯一的一个被称作“最后一个”的数据元素
除第一个外,集合中的每个数据元素均只有一个前驱
除最后一个外,集合中的每个数据元素均只有一个后继
2. 线性表的顺序存储结构
 
顺序表:
定义:用一组地址连续的存储单元存放一个线性表叫~
元素地址计算方法:
LOC(ai)=LOC(a1)+(i-1)*L
LOC(ai+1)=LOC(ai)+L
其中:
L— 一个元素占用的存储单元个数
LOC(ai)— 线性表第i个元素的地址
特点:
实现逻辑上相邻—物理地址相邻
实现随机存取
实现:可用C语言的一维数组实现
3. 线性表的基本操作
 
(1) InitList-Sq (L)初始化操作函数。生成一个空的线性表L。
(2) LENGTH (L) 求表长度的函数。函数值为线性表L中数据元素的个数。
(3) GET (L, i) 取表中元素的函数。当1≤ i ≤ LENGTH(L)时,函数值为线性表L中第i个数据元素,否则返回一特殊值。i是该数据元素在线性表中的位置序号。
(4) LOCATE (L, x)    定位函数。给定值x,在线性表L中若存在和x相等的数据元素,则函数返回和x相等的数据元素的位置序号,否则返回0。若线性表中存在一个以上的和x相等的数据元素,则函数返回多个位置序号中的最小值,也就是表中第一个和x相等的元素的位置序号。
(5) Insertlist-Sq(L, b, i) 插入操作。在给定线性表L中第i(1≤ i ≤ LENGTH(L) + 1)个数据元素之前插入一个新的数据元素b, 使原来线性表的长度n变成n + 1。
(6) ListDelete-Sq(L, i) 删除操作。删除在给定线性表L中第i (1≤ i ≤ LENGTH(L))个数据元素,使原来线性表的长度n变成n -1。
(7) EMPTY(L) 判空表函数。若L为空表,则返回布尔值“真”, 否则返回布尔值“假”。
(8) CLEAR(L)表置空操作。不管原来的线性表L是空表还是非空表,操作结果将L表置空。
以上基本操作中,(1),(5),(6),(8) 是加工型操作,其他都是引用型操作
4. 线性表原始定义
 
define LIST_INIT_SIZE    100 // 初次分配空间量
define  LISTINCREAENT    10   // 每次分配增量
Typedef   struct {
        ElemType *elem;        // 数组指针表的基址
        int   length;           // 当前元素个数
        int   listsize;     // 任何时刻能存最多元素个数
}SqList;
构成一个空线性表
 Status InitList-Sq(SqList &L)
{
    L.elem=(ElemType*)malloc(LIST-INIT-        SIZE*sizeof(ElemType));
   if(! L.elem) exit(OVERFLOW);   // 分配失败   L.length = 0;               // 数据元素个数为0
   L.Listsize =LIST_INIT_SIZE;  // 最多元素个数
   return OK;                     L.Listsize
}
算法实现:
void Insertlist(seqlist *L,ElemenType x,int i)
{
   int j ;
   if (i <1 ||i> L->length+1)   Error(position error);
   if(L->length+1 >= L->listsize) Error( overflow);
   For ( j = L->length-1 ;j >= i –1; j--)
   L->elem[j+1] = L->elem[j] ;
   L->elem[ i-1]= x
   L->length+ +;
}
 
当预定义的空间用完后,没有动态再给用户分配空间的功能。下面给出功能强的算法
 
Status ListInsert-Sq(SqList &L,int i,ElemenType e) {
     if (i <1 ||i > L.length+1) return ERROR;       // 位置不合法
     if (L.length >= L.listsize) {                                //预定义空间用完
        newbase = (ElemType *) realloc(L.elem,      // 动态再分配
                  (L.listsize+LISTINCREMENT) *sizeof(ElemType));
         if (!newbase) exit (OVERFLOW);               //再分配失败
         L.elem =newbase;                                          //新基值
         L.listsize +=LISTINCREMENT;                 //增加存储容量
        }
       q = & (L.elem[i-1]);                                         // 保存插入位置
       for ( p = &(L.elem[L.length –1]); p>=q; --p)
       * (p+1) =*p;                   // 移动相关数据为新数据插入准备空间
       *q = e;                      // 插入新数据         
 ++L.length;                                             // 长度增加 1          
       return OK;
 }
现在,分析该算法的时间复杂性。:该插入算法的基本操作是元素后移操作。执行元素后移的次数是 n - i +1。可以看到移动元素的次数不仅和表长有关,而且还与插入元素的位置i有关。当i = n + 1时,无须移动元素,当i = 1时,则元素后移将执行n次,也就是说该算法在最好情况下时间复杂度是O(1),最坏情况下时间复杂度是O(n)。进一步分析算法的平均性能:考虑在长度为n的线性表中插入一个元素,令Eis为移动元素的平均次数,在表中第i个元素前插入一个元素要移动元素的次数为n - i + 1,故
 
Eis=∑ Pi(n-i+1)
Pi表示在表中第 i个位置前插入一个元素的概率,假设在表中任何有效位置前(1 ≤ i ≤ n + 1 )插入元素的机会是均等的,则
Pi=1/(n+1)
因此
Eis=∑ (n-i+1)/(n+1)=n/2
 
也就是说,在顺序表上做插入操作,平均要移动表的一半元素。就数量级而言,它是线性阶的,算法的平均时间复杂度为 O(n)。
对后面的各种算法,我们不再详细分析和推导算法的时间复杂度,对有些算法则只给出推导的结果。
故在顺序表中插入或删除一个元素时,平均移动表的一半元素,当 n很大时,效率很低
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值