初级练手题之list

最常用的数据结构有LISTliststringmap。我们已经练习过LISTstring,现在练习list,双向链表。

注意双向链表有多种变形,比如非环结果双向链表,普通环行双向链表,多一个头节点的环行双向链表。不同的变形版本,对代码的复杂度有很微妙的影响。

typedef struct

{

    //任何你认为需要的字段

} LIST;

 

提供如下形式的算法函数

1)  LIST Create(void); 创建一个空链表,里面元素个数为0

    LIST Create_n(int n);创建一个空链表,里面元素个数为n,每个元素都调用Init_T函数进行了赋初值。

    LIST Create_n_t(int n, T t);创建一个空链表,里面元素个数为n,每个元素都赋初值为t

    void   Destory(LIST *);销毁掉链表,回收内存

2)  int Size(LIST *);获得LIST里的元素个数

3)  T * Front(LIST *);获得LIST里的第一个元素的指针。请说明元素个数为0时,你的函数返回什么结果

    T * Back(LIST *);获得LIST里的最后一个元素的指针。请说明元素个数为0时,你的函数返回什么结果

4)  T * Begin(LIST *); T * End(LIST *);返回的2个指针构成半闭半开区间[begin, end)指示出链表里所有元素。

所谓半闭半开区间就是包括begin所指元素,但不包括end所指元素。半闭半开区间是数据使用上一个极重要的概念,因为它能表示空集合。配合下面的Next,你就可以在不管是否有元素的情况下都可简单地进行遍历了。

for (T * p = Begin(&v); p != End(&v); Next(&v, p))

{

    //Do Something Here!

}

    T * Next(LIST *, T *);假定传入的指针确保指向LIST里的某个元素,给出它的下一个元素的指针。请说明已经指向最后一个元素时,你的函数返回什么结果。

    T * Prev(LIST *, T *);假定传入的指针确保指向LIST里的某个元素,给出它的前一个元素的指针。请说明已经指向第一个元素时,你的函数返回什么结果。

5)  T * Find(LIST *, T t);搜索第一个值为t的元素,返回其指针。请说明没找到时,你的函数返回什么结果。

    int Count(LIST *, T t);计算值为t的元素的个数

6)  T * Insert(LIST *, T * pos, T t);t插入到指针pos所指元素之前。返回新插入的元素的指针。

    T * InsertRange(LIST *, T * pos, T * first, T * last);[first, last)所指区间中所有元素保持原顺序插入到pos所指元素之前。返回新插入的第一个元素的指针。

void Push_Back(LIST * T t);在链表最后追加一个元素。

void Push_Front(LIST *, T t);在链表最开头增加一个元素。

    T * Erase(LIST *, T * pos);删除指针pos所指元素。返回被删除的元素的下一个元素的现在的指针。

    T * EraseRange(LIST *, T * first, T * last);删除指针[first, last)所指区间中的元素。返回最后一个删除的元素的下一个元素的现在的指针。

void Pop_Back(LIST *, T t);删除最后一个元素。

void Pop_Front(LIST *, T t);删除最开头的那个元素。

    void Clear(LIST *);清空所有元素。

    BOOL Remove(LIST *, T t);删除所有值为t的元素。返回“是否进行了删除”。

7)  void Assign(LIST * l, const LIST * r);使得l所指内存拥有和r完全相同的元素,而不是l.pr.p指向相同的地址。注意内存的分配和释放。

    void Swap(LIST * l, LIST * r);使得l拥有原来r的元素,r拥有l原来的元素。

LIST Create_byLIST(const LIST * v)//创建和v具有完全相同元素的新LIST

LIST Create_byArray(const T * first, const T * last)//创建和[first, last)所指数组区间相同的元素的新LIST

 

8)      附加题:

    BOOL Empty(const LIST * v)//如果没有元素,返回TRUE,其它情况返回FLASE

    void  Assign_byArray(LIST * v, const T * first, const T * last)//使得v现在含有和[first, last)所指数组区间相同的元素

    BOOL Equal(const LIST * l, const LIST * r)//2LIST元素个数并且按顺序,每个元素都相同时,返回TRUE

BOOL Less(const LIST * l, const LIST * r)//按字典序进行比较,l < r时返回TRUE。字典序就是 a开始的所有单词 < b开头的所有单词;a在所有a开头的单词里最小;其它a开头的单词根据第二个字母起继续比较。

9)      提高题:

实现FindCountRemove操作的扩展。

    要能完成比如“Count(LIST *, XXXXXX);能计算所有值大于x的元素的个数”这样的通用问题。

 

10)   再提高题:

LISTcreate函数创建后,因为分配了内存,所以必须用destory销毁的。而且每create一次,就得有且仅有一次对应的destory

如果有如下代码LIST v1 = CREATE_n(2);

              LIST v2 = CREATE_n(3);

              v2 = v1;

那么将导致v2create过程中分配的内存就泄漏了。

所以,问题是:如何能防止不小心的v2 = v1这类行为?

在你们的LIST代码里想办法完成,而不是指望使用LIST的人总不犯错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值