CLRS 10.2链表

来源:互联网 发布:批量复制软件 编辑:程序博客网 时间:2024/06/05 07:39

10.2-1
插入操作可以,删除操作不能,除非你给出要删除对象的前一个指针。

10.2-2
不带头结点的单链表,在头部插入和删除就可以实现栈。

#include <iostream>using std::cout;using std::endl;struct list_t{    int key;    list_t *next;};void push(list_t **list,int key){    list_t *node = new list_t;    node->next = *list;    node->key = key;    *list = node;}int pop(list_t **list){    if(*list == NULL)    {        cout << "List is Empty" << endl;        return -1;    }    int ret = (*list)->key;    list_t *node = *list;    *list = (*list)->next;    delete node;    return ret;}void print(list_t *list){    while(list != NULL){        cout << list->key << ' ';        list = list->next;    }}int main(){    list_t *list = NULL;    push(&list,8);    push(&list,5);    push(&list,3);    pop(&list);    print(list);    return 0;}

10.2-3
出队的时候在头部删除,入队的时候在尾部插入,需要在尾部添加一个指针以记录尾部。

10.2-4
将哨兵的值设为 k

LIST-SEARCH'(L, k):  x = L.nil.next  L.nil.key = k  while x.key ≠ k      x = x.next  return x

10.2-5
采用带头结点的循环链表,对SEARCH采用练习10.2-4中的方法,代码如下:

#include <iostream>using std::cout;using std::endl;struct node_t{    int key;    node_t *next;};struct list_t{    node_t nil;};void init(list_t *list){    list->nil.key = 0;    list->nil.next = &(list->nil);}node_t *SEARCH(list_t *list, int key){    node_t *node = list->nil.next;    list->nil.key = key;    while(node->key != key)        node = node->next;    if(node == &(list->nil))        return NULL;    else return node;}void INSERT(list_t *list, int key){    node_t *node = new node_t;    node->key = key;    node->next = list->nil.next;    list->nil.next = node;}void DELETE(list_t *list,int key){    node_t *node = &(list->nil);    while(node->next != &(list->nil))    {        if(node->next->key == key)        {            node_t *del = node->next;            node->next = node->next->next;            delete del;        }        else node = node->next;    }}int main(){    list_t head,*list = &head;    init(list);    INSERT(list,8);    INSERT(list,3);    INSERT(list,7);    node_t *node = SEARCH(list,3);    if(node != NULL)        cout << node->key << endl;    else cout << "not exist" << endl;    DELETE(list,3);    node = SEARCH(list,3);    if(node != NULL)        cout << node->key << endl;    else cout << "not exist" << endl;    return 0;}

10.2-6
使用双链表,把第一个链表的尾结点和第二个链表的第一个结点相连。

10.2-7
使用头插法即可实现逆转。代码为带头结点的循环单链表。

#include <iostream>using std::cout;using std::endl;struct node_t{    int key;    node_t *next;};struct list_t{    node_t nil;};void init(list_t *list){    list->nil.key = 0;    list->nil.next = &(list->nil);}node_t *SEARCH(list_t *list, int key){    node_t *node = list->nil.next;    list->nil.key = key;    while(node->key != key)        node = node->next;    if(node == &(list->nil))        return NULL;    else return node;}void INSERT(list_t *list, int key){    node_t *node = new node_t;    node->key = key;    node->next = list->nil.next;    list->nil.next = node;}void DELETE(list_t *list,int key){    node_t *node = &(list->nil);    while(node->next != &(list->nil))    {        if(node->next->key == key)        {            node_t *del = node->next;            node->next = node->next->next;            delete del;        }        else node = node->next;    }}void REVERSE(list_t *list){    node_t *node = list->nil.next;    list->nil.next = &(list->nil);    while(node != &(list->nil))    {        node_t *next = node->next;        node->next = list->nil.next;        list->nil.next = node;        node = next;    }}int main(){    list_t head, *list = &head;    init(list);    INSERT(list,8);    INSERT(list,4);    INSERT(list,2);    INSERT(list,10);    INSERT(list,-5);    REVERSE(list);    return 0;}

10.2-8
首先,需要知道异或的性质,我们根据 np 的定义有 np[x]=next[x] XOR prev[x],再由异或的性质有 next[x]=np[x] XOR prev[x]prev[x]=next[x] XOR np[x]。也就是说,如果我们知道本结点的下一个结点的地址,我们就能算出本结点的上一个结点地址,反之,知道上一个结点地址就知道下一个结点的地址。
对于在 O(1) 的时间内逆转,我们添加两个指针,分别指向头和尾,逆转的时候只需交换头指针和尾指针即可。
代码如下,感觉第一次会有点不可理解,在INSERT里面注释了不少,能理解INSERT应该就可以理解全部代码了。

#include <iostream>using std::cout;using std::endl;struct node_t{    int key;    node_t *np;};struct list_t{    node_t *head;    node_t *tail;};void init(list_t *list){    list->head = NULL;    list->tail = NULL;}void INSERT(list_t *list,int key){    node_t *node = new node_t;    node->key = key;    /**********    node->np = node->next ^ node->prev     ***********    ***每次插入一个节点的时候,node->next为空,node->prev就是尾指针指向的节点*/    node->np = (node_t *)(NULL ^ (unsigned)(list->tail));    /***     插入后节点后就需要修改原先的尾节点的np值,也就是尾指针指向的节点的np         ******    ****     list->tail->np = list->tail->np->next ^ list->tail->np->prev      ******    **** list->tail->np->next等于新插入节点地址,即node,list->tail->np->prev又需要继续异或 ******    ****     list->tail->np->prev = (后节点 ^ 自身),分别为 NULL,list->tail->np  ******/    if(list->tail)        list->tail->np = (node_t *)((unsigned)node ^ (NULL ^ (unsigned)(list->tail->np)));    if(!list->head)         //头指针为空,修改头指针的指向        list->head = node;    list->tail = node;      //修改头指针的指向}node_t *SEARCH(list_t *list, int key){    node_t *node = list->head;    node_t *prev = NULL;    node_t *next;    while(node)    {        if(node->key == key)            return node;        next = (node_t *)((unsigned)(node->np) ^ (unsigned)(prev));        prev = node;        node = next;    }    return NULL;}void DELETE(list_t *list,int key){    node_t *node = list->head;    node_t *prev = NULL;    node_t *next;    while(node)    {        if(node->key == key)        {            next = (node_t *)((unsigned)(node->np) ^ (unsigned)(prev));            if(prev)                    //删除的不是第一个节点                prev->np = (node_t *)((unsigned)(prev->np) ^ (unsigned)(node) ^ (unsigned)(next));            else list->head = next;     //修改头指针            if(next)                next->np = (node_t *)((unsigned)(next->np) ^ (unsigned)(node) ^ (unsigned)(prev));            else list->tail = prev;            node = next;        }        else        {            next = (node_t *)((unsigned)(node->np) ^ (unsigned)(prev));            prev = node;            node = next;        }    }}void REVERSE(list_t *list){    node_t *temp;    temp = list->head;    list->head = list->tail;    list->tail = temp;}void PRINT(list_t *list){    node_t *node = list->head;    node_t *prev = NULL;    node_t *next;    while(node)    {        cout << node->key << ' ';        next = (node_t *)((unsigned)(node->np) ^ (unsigned)(prev));        prev = node;        node = next;    }}int main(){    list_t Head, *list = &Head;    init(list);    INSERT(list,8);    INSERT(list,0);    INSERT(list,-6);    INSERT(list,2);    INSERT(list,-7);    PRINT(list);    cout << endl;    REVERSE(list);    PRINT(list);    cout << endl;    DELETE(list,2);    DELETE(list,-7);    PRINT(list);    return 0;}
0 0
原创粉丝点击