您的位置:首页 > 理论基础 > 数据结构算法

2.2线性表的顺序表示和实现

2017-01-26 20:49 260 查看
下面这张图是线性表插入数据的原理图:



算法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,把另外那条链,剩下的加进去(都是非递减排列的)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息