【编程练习题】

 本章编程练习题中的顺序表和线性链表的类型定义如下:
  struct SqList // 顺序表
  {
   ElemType *elem;
   int length;
   int listsize;
  };

  typedef struct LNode* SLink;
  struct LNode // 单链表结点
  {
   ElemType data;
   SLink next;
  };
  typedef SLink LinkList; // 单链表(带头结点)

  typedef struct DuLNode* DuLink;
  struct DuLNode // 双链表结点
  {
   ElemType data;
   int freq;
   DuLink prior, next;
  };
  typedef DuLink DuLinkList; // 双向循环链表(带头结点)

  struct PolyTerm
  {
   int coef;
   int exp ;
  };

 1. 设顺序表 a 中的数据元素递增有序。试写一算法,将 x 插入到顺序表的适当位置上,以保持该表的有序性。
  void InsertOrderList( SqList &a, ElemType x)
  // 已知顺序表 a 中的数据元素递增有序,将 x 插入到顺序表的适当位置上,
  // 以保持该表的有序性。

 2. 设A=(,…,) 和B=(,…,) 均为顺序表,A' 和B' 分别为 A 和 B 中除去最大共同前缀后的子表(例如,A=(x,y,y,z,x,z),B=(x,y,y,z,y,x,x,z),则两者中最大的共同前缀为(x,y,y,z),在两表中除去最大共同前缀后的子表分别为A'=(x,z) 和 B'=(y,x,x,z))。若 A'= B'= 空表,则 A = B;若 A'= 空表,而 B'≠ 空表,或者两者均不为空表,且 A'的首元小于 B'的首元,则 A<B;否则 A>B。试写一个比较 A、B 大小的算法。(请注意:在算法中,不要破坏原表 A 和 B,并且,也不一定先求得 A'和 B'才进行比较)
  char Compare(SqList A, SqList B)
  // 已知顺序表A和B, 返回 '<'(若 'A<B') 或 '='(若 'A=B') 或 '>'(若 'A>B')

 3. 已知线性表中的元素以值递增有序排列,并以单链表作存储结构。试写一高效的算法,删除表中所有值大于 mink 且小于 maxk 的元素 (若表中存在这样的元素)同时释放被删结点空间。(注意:mink 和 maxk 是给定的两个参数值,它们的值可以和表中的元素相同,也可以不同)
  void del_between_mink_and_maxk( LinkList& hlink, ElemType mink, ElemType maxk )
  // hlink 为指向单链表头结点的指针,
  // 删除链表中其值介于 mink 和 maxk 之间的结点。

 4. 试写一算法,实现顺序表的就地逆置,即利用原表的存储空间将线性表(,…,) 逆置为(,,…,)。
  void invert_sqlist(SqList& va)
  // 逆转顺序表 va

 5. 试写一算法,对单链表实现就地逆置。
  void invert_linkst(LinkList& hlink)
  // 逆转以 hlink 为头指针的单链表

 6. 假设有两个按元素值递增有序排列的线性表 A 和 B,均以单链表作存储结构,请编写算法将 A 表和 B 表归并成一个按元素值递减有序(即非递增有序,允许表中含有值相同的元素)排列的线性表 C,并要求利用原表(即 A 表和 B 表)的结点空间构造 C 表。
  void union_linkst( LinkList& lc, LinkList la, LinkList lb )
  // 将两个(分别以 la 和 lb 为头指针的)增序有序链表
  // 归并为一个逆序(非递增)有序链表,归并后的链表的头指针为 lc 。

 7. 假设以两个元素依值递增有序排列的线性表 A 和 B 分别表示两个非纯集合(即同一表中可能存在值相同的元素),现要求构成一个线性表 C,其元素为 A 和 B 中元素的交集,且表 C 中的元素也依值递增有序排列并各不相同,并要求 C 表和 A 表共享存储空间。
  void intersect_sqlist( SqList& va, SqList vb )
  // va 和 vb 均为有序(值自小而大)顺序表,且同一表中可能有值相同的
  // 数据元素,本函数实现从 va 中删除所有值和 vb 中元素不相同的元素,
  // 并使最后所得的顺序表 va 中的数据元素值均各不相同。

 8. 对单链表重新编写和题7相同要求的算法。
  void intersect_linkst( LinkList& hc, LinkList ha, LinkList hb )
  // 构造有序链表 hc 表示"纯集合"C 为有序链表 ha 表示的
  // 非纯集合 A 和 有序链表 hb 表示的非纯集合 B 的交集

 9. 已知 A、B 和 C 为三个递增有序的线性表,现要求对 A 表作如下操作:删去那些既在 B 表中出现又在 C 表中出现的元素。试对顺序表编写实现上述操作的算法,并分析你的算法的时间复杂度(注意:题中没有特别指明同一表中的元素值各不相同)。
  void difference_sqlist( SqList& a, SqList b, SqList c )
  // 从增序顺序表 a 中删除那些既在 b 表中出现又在 c 表中出现的数据元素

 10. 对单链表重新编写和题9相同要求的算法。
  void difference_linkst(LinkList& la, LinkList lb, LinkList lc)
  // 从增序有序链表 la 中删除那些既在 lb 表又在 lc 表中出现的数据元素

 11. 设有一个双向循环链表,每个结点中除有 pre、data 和 next 三个域外,还增设了一个访问频度域 freq。在链表被起用之前,频度域 freq 的值均初始化为零,而每当对链表进行一次 LOCATE(L,x) 的操作后,被访问的结点(即元素值等于 x 的结点)中的频度域 freq 的值便增 1,同时调整链表中结点之间的次序,使其按访问频度非递增的次序顺序排列,以便始终保持被频繁访问的结点总是靠近表头结点。试编写符合上述要求的 LOCATE 操作的算法。
  DuLink visit( DuLinkList dh, ElemType x )
  // 本题要求返回指向被访问的结点的指针,若链表中不存在和 x 相等的元素,
  // 这返回 NULL。dh 是指向双向循环链表头结点的指针,结点中还增设了一个
  // 访问频度域 freq,其初值为 0,一旦结点被访问,其访问频度域的值增 1,
  // 并始终保持链表中的结点按 freq 的值非递增排列。

 12. 已知稀疏多项式 ,其中n=em>em-1>…>e1≥0,≠0 (i=1,2,…,m), m≥1采用如下说明的顺序存储结构,编写求 的算法( 为给定值)。
  struct SqPoly
  {
   PolyTerm *data;
   int length ;
  };
  float evaluate( SqPoly pn, float x )
  // pn.data[i-1].coef 存放 ,pn.data[i-1].exp 存放 (i=1,2,…,m)
  // 本算法计算并返回多项式的值。不判别溢出。
  // 此外,入口时要求0≤e1<e2<…<em,算法内不对此再作验证?

 13. 假设以如下说明的循环链表作稀疏多项式的存储结构,编写求其导函数的算法,要求利用原多项式中的结点空间存放其导函数(多项式),同时释放所有无用(被删)结点。
  typedef struct PolyNode* PolyLink;
  struct PolyNode
  {
   PolyTerm data;
   PolyLink next;
  };
  typedef PolyLink LinkedPoly ;
  void difference ( LinkedPoly& pa )
  // 稀疏多项式 pa 以循环链表作存储结构,将此链表修改成它的导函数,
  // 并释放无用结点
 

 
【编程练习题】