zoukankan      html  css  js  c++  java
  • 《算法导论》笔记 第10章 10.2 链表

    【笔记】

    哨兵不能降低各种操作的渐进时间界,但可以降低常数因子,简化代码。

    template <typename ITEM>
    class list {
    private:
        struct DATA{
            ITEM key;
            DATA *prev, *next;
            DATA() {}
            DATA(ITEM x):key(x) {}
        }NIL;
        DATA *nil;
        int sz;
    
    public:
        list(){
            nil = &NIL;
            nil->next=nil;
            nil->prev=nil;
        }
        ~list(){
            while (sz) remove(nil->next);
        }
        void insert(ITEM x) {
            DATA *p = new DATA(x);
            p->next = nil->next;
            nil->next->prev = p;
            nil->next = p;
            p->prev = nil;
            sz++;
        }
        bool search(ITEM k) {
            DATA* p = nil->next;
            while (p != nil && p->key != k) p = p->next;
            return p != nil;
        }
        void remove(DATA* p) {
            p->prev->next = p->next;
            p->next->prev = p->prev;
            delete p;
            sz--;
        }
    };


    【练习】

    10.2-1 动态集合上的操作INSERT能否用一个单链表在O(1)时间内实现?对DELETE操作呢?

    INSERT 能在O(1)内实现,DELETE不能。


    10.2-2 用一单链表L实现一个栈,要求PUSH和POP操作的时间仍为O(1)。

    const int MAXN = 10;
    struct NODE{
        int key;
        NODE *next;
        NODE():key(0) {}
        NODE(int x):key(x) {}
    };
    NODE* head[MAXN];
    void prepare(int L) {
        head[L] = NULL;
    }
    NODE* search(int L,int k) {
        NODE* p = head[L];
        while (p!=NULL && p->key!=k) p = p->next;
        return p;
    }
    void insert(int L,int x) {
        NODE *p = new NODE(x);
        p->next = head[L];
        head[L] = p;
    }
    void remove(int L,NODE *p) {
        if (p==NULL) return;
        if (head[L] == p) {
            head[L] = p->next;
            delete p;
            return;
        }
        NODE *t = head[L];
        while (t->next!=NULL && t->next!=p) t = t->next;
        if (t->next==NULL) return;
        t->next = p->next;
        delete p;
    }
    
    void push(int L,int x) {
        insert(L,x);
    }
    int pop(int L) {
        if (head[L]==NULL) return -1;
        int res = head[L]->key;
        remove(L,head[L]);
        return res;
    }

    10.2-3 用一单链表L实现一个队列,要求ENQUEUE和DEQUEUE操作的时间仍为O(1)。

    struct NODE{
        int key;
        NODE *next;
        NODE():key(0) {}
        NODE(int x):key(x) {}
    };
    NODE *head[MAXN],*tail[MAXN];
    void prepare(int L) {
        head[L] = NULL;
        tail[L] = NULL;
    }
    void push(int L,int x) {
        NODE *p = new NODE(x);
        p->next = NULL;
        if (head[L] == NULL) head[L] = p;
        if (tail[L] != NULL) tail[L]->next = p;
        tail[L] = p;
    }
    int pop(int L) {
        if (head[L]==NULL) return -1;
        int res = head[L]->key;
        NODE *p = head[L];
        head[L] = head[L]->next;
        delete p;
        return res;
    }

    10.2-4 如前文所写,LIST-SEARCH'过程的每一次循环迭代都需要做两个测试:一个检查x!=nil[L],一个检查key[x]!=k。说明如何能够在每次迭代中,省去对x!=nil[L]的检查。

    将哨兵的值赋为要查找的值,在循环结束后判断找到的结点是否为哨兵即可。


    10.2-5 用环形单链表来实现字典操作INSERT、DELETE和SEARCH,并给出它们的运行时间。

    O(1) O(n) O(n) ?


    10.2-6 动态集合操作UNION以两个不想交的集合S1和S2作为输入,输出集合S=S1∪S2包含了S1和S2的所有元素。该操作常常会破坏S1和S2。说明应如何选用一种数据结构,以便支持在O(1)时间内的UNION操作。

    采用链表,head[L]指向表头,tail[L]指向表尾。合并时将tail[S1]->next 指向head[S2]。新集合的表头为head[S1]。


    10.2-7 请给出一个θ(n)时间的非递归过程,它对含n个元素的单链表的链进行逆转。除了链表本身占用的空间外,该过程应仅使用固定量的存储空间。

    void reverse(int L) {
        NODE *pre, *p, *nxt;
        pre = NULL;
        p = head[L];
        nxt = p->next;
        while (p) {
            if (nxt == NULL) {
                head[L] = p;
                break;
            }
            p->next = pre;
            pre = p;
            p = nxt;
            nxt = nxt->next;
        }
    }

    *10.2-8 说明如何对每个元素仅用一个指针np[x]来实现双链表。

    用异或即可,由a^b^b=a可知,np[x]中储存的是next[x]^prev[x]。

    从前向后遍历时,prev[x]已知,令pt为prev[x],next[x]即为np[x]^pt,pt初值存在head[L]中。

    从后向前遍历时,next[x]已知,令pt为next[x],prev[x]即为np[x]^pt。


  • 相关阅读:
    单词 统计
    第十周学习记录
    梦断代码阅读笔记03
    梦断代码阅读笔记02
    梦断代码阅读笔记01
    用户模板和用户场景
    第九周学习记录
    分享好友-分享朋友圈
    生命周期函数-页面刷新
    底部导航的设置
  • 原文地址:https://www.cnblogs.com/cyendra/p/3681504.html
Copyright © 2011-2022 走看看