码迷,mamicode.com
首页 > 其他好文 > 详细

【链表】双向链表

时间:2014-11-11 22:44:56      阅读:308      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   io   color   ar   os   sp   for   

一开始我就觉得双向链表非常非常的麻烦,但是老师出了一道上机题。debug了好久才过(博主比较菜还请大家见谅),所以贴出来共享下。

链表比较麻烦的就是插入和删除操作。一定要先弄懂指针到底是指向哪里的。

我们首先用结构体struct 定义了node,node中包括了data(这个结点存的数据),*prev(指向上一个节点的指针)和*next(指向下一个节点的指针)

我在构造函数中首先新建了头尾结点,于是插入删除操作可以避免边界的讨论。

插入时,我们假定要在A结点和B结点中插入C结点,那么首先我们要新建一个节点(我用的是new),(假设我们用temp指针指向这个新的结点)然后我们把要存的元素复制给data,所以我们让temp -> data(令temp指针指向data),在把元素复制给data。 在c++ 中就是 entry(我们要存的元素) = temp -> data。然后我们令temp -> next = B, temp -> prev = A,那么C的下一个节点就是B,上一个节点就是A。

然后我们要把c结点插入A结点和B结点之间,所以我们用setPosition函数让*current 指向A结点, 那么current -> next 就会指向B结点。这时候我们要注意赋值的顺序。我们首先把current -> next -> prev = C(表示A结点的下一个节点的上一个节点,也就是B结点的上一个节点),于是B结点的prev就会指向C结点,所以B结点的上一个就会变成C结点。同理我们current -> next = C,把A的下一个节点变成了C,于是我们就完成插入插入操作。// 一定要注意current的赋值顺序。

删除操作同理,首先用setPosition找到要删除的结点。这是我们要定义多一个临时的指针temp来存这个结点(否则如果我们没有delete的话,这个结点没有指针指向它,会变成内存垃圾,如果我们delete current的话会整个链表就没有指针可以访问了,所以我们在完成操作之后要delete temp来避免这些问题)如果怕删除出错的话可以定义*p = current -> prev, *q = current -> next,用p,q指针分别指向要删除结点的前一个结点和后一个结点。然后我们让p -> next = q, q -> prev = p就可以了,如果嫌这个麻烦也可以直接 current -> next -> prev = current -> prev; current -> prev -> next = current -> next; 最后我们可以让current = current -> next  或者current = current -> prev,最后delete掉temp,完成删除操作。

这份代码的函数是老师给定好的,private用了current指针而没有用head 和 而且加了curPosition. (因为如果用head的话速度会慢一点,因为插入等函数要从head开始遍历,所以每次遍历到当前的position需要 position - 1次,而如果用curPosition的话就会快一点// 因为current函数到Posiiton的距离一定比head 到Position的距离短 //  如果是连续插入的话,那么curPosition到下一个节点的距离为1,而head到position的距离就是 position -1 所以用current会快)

还有就是由于有insert(插入),和retrieve(获得position位置的元素)函数,所以我在深复制的时候直接用了insert和retrieve。

以下是代码

bubuko.com,布布扣
#include <iostream>
#include <cstdlib>
using namespace std;
enum Error_code
{
         success,
         underflow,
         overflow
};
template <class List_entry>
struct Node
{
         List_entry entry;
         Node<List_entry> *next;
         Node<List_entry> *back;
};
template <class List_entry>
class MyList
{
public:
         MyList() {
           count =  0;
           curPosition = -1;
           current = new Node<List_entry>;// head
           current -> entry = -1;
           current -> next = new Node<List_entry>; // tail
           current -> next -> entry = -1;
           current -> back = NULL;
           current -> next -> back = current;
           current -> next -> next = NULL;
         }
         ~MyList() {
            clear();
            Node<List_entry>*p = current, *q = current -> next; // 头结点和尾结点不能在clear里面删除,否则会出现clear后在insert的时候就没有头尾结点了 
            delete p;
            delete q;
            current = NULL;
         }
         // 拷贝构造函数和赋值运算符重载,注意深拷贝与浅拷贝的差异
         MyList(const MyList<List_entry> &copy) {
           count =  0;
           curPosition = -1;
           current = new Node<List_entry>;// head
           current -> entry = -1;
           current -> next = new Node<List_entry>; // tail
           current -> next -> entry = -1;
           current -> back = NULL;
           current -> next -> back = current;
           current -> next -> next = NULL;
           List_entry entry;
           while (count < copy.size()) {
             copy.retrieve(count, entry);
             insert(count, entry);
           }
           setPosition(copy.curPosition);
         }
         void operator =(const MyList<List_entry> &copy) {
           count =  0;
           curPosition = -1;
           current = new Node<List_entry>;// head
           current -> entry = -1;
           current -> next = new Node<List_entry>; // tail
           current -> next -> entry = -1;
           current -> back = NULL;
           current -> next -> back = current;
           current -> next -> next = NULL;
           List_entry entry;
           while (count < copy.size()) {
             copy.retrieve(count, entry);
             insert(count, entry);
           }
           setPosition(copy.curPosition);
         }
         // 清空list
         void clear() {
           List_entry entry;
           while (size()) {
             remove(count - 1,entry);
           }
           count = 0;
         }
         // 判断list是否为空
         bool empty() const {
           return (count == 0) ? 1 : 0;
         }
         // 判断list是否已满
         bool full() const {
           return false;
         }
         // 获取list的元素数量
         int size() const {
           return count;
         }
         // 在第position个位置插入值为entry的元素,如果position为0则插入在链表头,依次类推
         // 若position < 0 或者 position > count,则返回underflow
         Error_code insert(int position, const List_entry &entry) {
           if (position < 0 || position > count) return underflow;
           Node<List_entry>*p = new Node<List_entry>;
           p -> entry = entry;
           setPosition(position - 1);
           p -> next = current -> next;
           p -> back = current;
           current -> next -> back = p;
           current -> next = p;
           count++;
           return success;
         }
         // 删除第position个位置的元素,并将该元素的值保存在entry中
         // 若position < 0 或者 position >= count,则返回underflow
         Error_code remove(int position, List_entry &entry) {
           if (position < 0 || position >= count) return underflow;
           setPosition(position);
           Node<List_entry> *p = current;
           entry = p -> entry;
           p -> next -> back = p -> back;
           p -> back -> next = p -> next;
           current = current -> next;
           delete p;
           count--;
           return success;
         }
         // 获取第position个位置的元素,保存在entry中
         // 若position < 0 或者 position >= count,则返回underflow
         Error_code retrieve(int position, List_entry &entry) const {
           if (position < 0 || position >= count) return underflow;
           setPosition(position);
           entry = current -> entry;
           return success;
         }
         // 将第position个位置的元素替换为entry
         // 若position < 0 或者 position >= count,则返回underflow
         Error_code replace(int position, const List_entry &entry) {
           if (position < 0 || position >= count) return underflow;
           setPosition(position);
           current -> entry = entry;
           return success;
         }
         // 用visit函数遍历list内所有的元素
         void traverse(void (*visit)(List_entry &)) {
           for (int i = 0; i < size(); i++) {
             setPosition(i);
             visit(current -> entry);
           }
         }
protected:
         int count;                                                                          // 记录list内元素数量
         mutable int curPosition;                                   // current指针的位置编号
         mutable Node<List_entry> *current;                 // current指针
         // 设置current指针的位置,指向第position个位置
         void setPosition(int position) const {
           if (position > curPosition)
             for (; curPosition < position; curPosition++) current = current -> next;
           else if (position < curPosition)
             for (; curPosition > position; curPosition--) current = current -> back;
         }
};
View Code


链表比较复杂,所以博主啰嗦了一些,如果各位有更好的方法,还请指导,谢谢大家了。

【链表】双向链表

标签:style   blog   http   io   color   ar   os   sp   for   

原文地址:http://www.cnblogs.com/tonyyangsysu/p/4090550.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!