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

来源:互联网 发布:淘宝如何买东西 编辑:程序博客网 时间:2024/06/07 05:36

下面这张图是线性表插入数据的原理图:


算法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,把另外那条链,剩下的加进去(都是非递减排列的)。

1 0
原创粉丝点击