您的位置:首页 > 其它

CLRS 10.2链表

2015-11-28 08:47 260 查看
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

将哨兵的值设为 kk。

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

首先,需要知道异或的性质,我们根据 npnp 的定义有 np[x]=next[x]np[x] = next[x] XOR prev[x] prev[x],再由异或的性质有 next[x]=np[x]next[x] = np[x] XOR prev[x],prev[x]=next[x]prev[x],prev[x] = next[x] XOR np[x] np[x]。也就是说,如果我们知道本结点的下一个结点的地址,我们就能算出本结点的上一个结点地址,反之,知道上一个结点地址就知道下一个结点的地址。

对于在 O(1)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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: