下面这张图是线性表插入数据的原理图:
算法2.3:一般情况下,在第(1<=i<=n)个元素之前插入一个元素时,需将第n至第i(共n-i+1)个元素向后移动一个位置。
我们来看看书上提供的伪代码:
Status ListInsert_Sq(SqList &L, int i, ElemType e) {
// 在顺序线性表L的第i个元素之前插入新的元素e,
// i的合法值为1≤i≤ListLength_Sq(L)+1
ElemType *p;
if (i < 1 || i > L.length+1) return ERROR; // i值不合法
if (L.length >= L.listsize) { // 当前存储空间已满,增加容量
ElemType *newbase = (ElemType *)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof (ElemType));
if (!newbase) return ERROR; // 存储分配失败
L.elem = newbase; // 新基址
L.listsize += LISTINCREMENT; // 增加存储容量
}
ElemType *q = &(L.elem[i-1]); // q为插入位置
for (p = &(L.elem[L.length-1]); p>=q; --p) *(p+1) = *p;
// 插入位置及之后的元素右移
*q = e; // 插入e
++L.length; // 表长增1
return OK;
} // ListInsert_Sq
我们来分析下:
1.有一个叫Status的函数,顾名思义这是泛指某一状态,因为c语言没有泛型这个概念(C++中的tempate)所以书中用Status表示,可能是int,可能是double等等。
2.当i不再合法范围时,我们看到了一个ERROR这个,我估计这是一个宏(#define)可能是-1或者其他值。
3.当存储空间满了时他调用了realloc函数,这个函数全称是reallocate,顾名思义重新分配,
4.LISTINCREMENT是一个宏,值为10,意思是线性表增加10。
5.定义了两个元素类型指针(一个是p,一个是q),先把q指向要插入的元素前面那个元素(里面的elem也是元素类型指针)。
6.for循环这块,先把p指向顺序表最后一个元素(从0开始,所以要L.length-1),当p指到q后面的元素时循环成立,然后,p不停的前移。
7.在for循环里面,依次i把元素后移。
下面是删除
算法2.4:一般情况下,删除第i(1<=i<=n)个元素时将从第i+1至第n(共n-i)个元素依次向前移动一个位置
伪代码如下:
Status ListDelete_Sq(SqList &L, int i, ElemType &e) { // 算法2.5
// 在顺序线性表L中删除第i个元素,并用e返回其值。
// i的合法值为1≤i≤ListLength_Sq(L)。
ElemType *p, *q;
if (i<1 || i>L.length) return ERROR; // i值不合法
p = &(L.elem[i-1]); // p为被删除元素的位置
e = *p; // 被删除元素的值赋给e
q = L.elem+L.length-1; // 表尾元素的位置
for (++p; p<=q; ++p) *(p-1) = *p; // 被删除元素之后的元素左移
--L.length; // 表长减1
return OK;
} // ListDelete_Sq
下面我们来分析下:
1.前面几行到上面那了例子分析过来,在此不再分析。
2.因为下标是从0开始,所以删除第i个元素时为L.elem[i-1]。
3.q=L.elem+L.length-1我们分析下。这个是使得q指向链表的尾部。
4.for循环里面p先+1,当p>q时循环才停止,而在循环中,可知把p的值网前一个覆盖。
算法2.5:在线性表中查找指定元素的位置
下面是书上提供的伪代码。
int LocateElem_Sq(SqList L, ElemType e,
Status (*compare)(ElemType, ElemType)) {
// 在顺序线性表L中查找第1个值与e满足compare()的元素的位序。
// 若找到,则返回其在L中的位序,否则返回0。
int i;
ElemType *p;
i = 1; // i的初值为第1个元素的位序
p = L.elem; // p的初值为第1个元素的存储位置
while (i <= L.length && !(*compare)(*p++, e))
++i;
if (i <= L.length) return i;
else return 0;
} // LocateElem_Sq
下面我们来分析下:
1.这个LocateElem函数是看元素是坐落在哪,返回值是int说明他返回位置,一个参数是线性表,第二个参数是元素类型,第三个个参数我们可以理解为这是一个比较功能,并且我们从下面的那个while语句可以得知,这个compare函数当两参数值不相等时返回0,相等时返回1。
2.还有,我们可以看见一个这程序的一个思路,当找不到,或者出现某种其他错误时,他返回0。
算法2.6:已知顺序线性表La和Lb的元素按值非递减排列,归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列
下面是书上的代码:
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc) {
ElemType *pa,*pb,*pc,*pa_last,*pb_last;
pa = La.elem; pb = Lb.elem;
Lc.listsize = Lc.length = La.length+Lb.length;
pc = Lc.elem = (ElemType *)malloc(Lc.listsize*sizeof(ElemType));
if (!Lc.elem)
exit(OVERFLOW); // 存储分配失败
pa_last = La.elem+La.length-1;
pb_last = Lb.elem+Lb.length-1;
while (pa <= pa_last && pb <= pb_last) { // 归并
if (*pa <= *pb) *pc++ = *pa++;
else *pc++ = *pb++;
}
while (pa <= pa_last) *pc++ = *pa++; // 插入La的剩余元素
while (pb <= pb_last) *pc++ = *pb++; // 插入Lb的剩余元素
} // MergeList
分析如下:
1.函数为MergList_Sq什么我们这点这是混合链,参数可知Lc是要被修改的,与已知相符。
2.代码中有一个exit(OVERFLOW),这里面exit()里面的参数是一般是整数,所以我们可以知道这个OVERFLOW是宏,可能是-1,0,1,意思为溢出。
3.这里有一个算法,在第一个while里面把pa与pb指向的值进行比较,谁小把谁放到Lc,当有一个链到最后时,循环结束,进入第二个或第三个while,把另外那条链,剩下的加进去(都是非递减排列的)。