练习--实现双向链表

来源:互联网 发布:上古卷轴5男捏脸数据 编辑:程序博客网 时间:2024/06/09 20:03

1.题目(算法p103-p104):

实现一个双向链表,并且实现以下的函数:

(1)在指定的节点之前插入节点

(2)在指定的节点之后插入节点

(3)删除指定节点

(4)removeAfter(),接受一个链表节点作为参数,并删除该节点的后续节点

(5)find(),接受一个key值,如果链表中某个节点的data域的值跟key相等,那么就返回true,否则返回false


2.分析:双向链表存在着两个指针域,一个指向前面的节点,一个指向后面的节点,相对于单链表来说,双向链表的好处有:

i.便于删除节点,双向链表因为保存着上一个节点的地址,所以我们进行删除操作的时候所编写的代码会易读很多。

ii.插入和删除操作相对较少。


3.实现:

#ifndef LIST_HPP#define LIST_HPP#include <iostream>using namespace std;//定义节点类template <typename T>class Node{public:Node(T item) : next(NULL), pre(NULL), data(item){}~Node(){}Node* next;Node* pre;T data;};//链表template <typename T>class MyList{public:MyList();~MyList();void insertBefore(Node<T>* position, T data);   //在指定节点之前插入节点void insertAfter(Node<T>* position, T data);//在指定节点之后插入节点void insert(T data);//在表尾插入节点void deleteNode(Node<T>* position);//删除指定节点void removeAfter(Node<T>* position);//删除指定节点之后的所有节点bool isEmpty();//判空void printList();//打印链表bool find(T data);//找到指定数据的节点Node<T>* at(int count);//找到位于链表第count个的节点Node<T>* getFirst() {return first;}//头指针Node<T>* getTail() {return tail;}//尾指针private:Node<T>* first;Node<T>* tail;int size;};template <typename T>MyList<T>::MyList() : first(NULL),tail(NULL), size(0){}template <typename T>MyList<T>::~MyList(){}template <typename T>void MyList<T>::insertBefore(Node<T>* position, T data){if (position == NULL && !isEmpty())//如果position 为空,且链表有数据的话,结束函数{return ;}if (isEmpty())//如果链表为空,那么就新建一个节点{Node<T>* currentNode = new Node<T>(data);first = tail = currentNode;}else if (position->pre == NULL)//如果在表头进行插入节点,那么就把新插入的节点当做头节点{Node<T>* currentNode = new Node<T>(data);currentNode->next = position;position->pre = currentNode;first = currentNode;}else//如果在两个节点之间插入节点{Node<T>* currentNode = new Node<T>(data);Node<T>* preNode = position->pre;preNode->next = currentNode;currentNode->pre = preNode;currentNode->next = position;position->pre = currentNode;}size++;}template <typename T>void MyList<T>::insertAfter(Node<T>* position, T data){if (position == NULL && !isEmpty()) //如果position 为空,且链表有数据的话,结束函数{return ;}if (isEmpty())   //如果链表为空,那么就新建一个节点{Node<T>* currentNode = new Node<T>(data);first = tail = currentNode;}else if (position->next == NULL) //如果在表尾进行插入节点,那么就把新插入的节点当做尾节点{Node<T>* currentNode = new Node<T>(data);currentNode->pre = position;position->next = currentNode;tail = currentNode;}else    //如果在两个节点之间插入节点{Node<T>* currentNode = new Node<T>(data);Node<T>* nextNode = position->next;nextNode->pre = currentNode;currentNode->pre = position;currentNode->next = nextNode;position->next = currentNode;}size++;}//在表尾进行插入操作template <typename T>void MyList<T>::insert(T data){if (isEmpty()){Node<T>* currentNode = new Node<T>(data);first = tail = currentNode;}else{Node<T>* currentNode = new Node<T>(data);tail->next = currentNode;currentNode->pre = tail;tail = currentNode;}size++;}//删除指定的节点template <typename T>void MyList<T>::deleteNode(Node<T>* position){if (isEmpty() || position == NULL)//如果传入参数不正确或者链表为空的话,结束调用{return ;}if (position == first)//如果是删除头节点{Node<T>* currentDelete = first;first = first->next;currentDelete->next = NULL;delete currentDelete;}else if (position == tail)//如果是删除尾节点{Node<T>* currentDelete = tail;tail = tail->pre;currentDelete->pre = NULL;delete currentDelete;}else//如果是删除中间节点{Node<T>* nextNode = position->next;Node<T>* preNode = position->pre;position->next = NULL;position->pre = NULL;nextNode->pre = preNode;preNode->next = nextNode;delete position;}size--;}//删除指定节点后面的所有节点template <typename T>void MyList<T>::removeAfter(Node<T>* position){int number = 0;Node<T>* currentNode = position->next;position->next = NULL;while (currentNode != NULL){Node<T>* deleteNode = currentNode;currentNode = currentNode->next;delete deleteNode;number++;}size -= number;}//打印链表template <typename T>void MyList<T>::printList(){if (size == 0){cout << "List is empty !" << endl;return ;}Node<T>* currentNode = first;while(currentNode != NULL){cout << currentNode->data << " ";currentNode = currentNode->next;}cout << endl;}//找到指定的节点,找到返回true,找不到返回falsetemplate <typename T>bool MyList<T>::find(T data){Node<T>* currentNode = first;bool result = false;while (currentNode != NULL){if (currentNode->data == data){result = true;break;}}return result;}//找到位于链表中count的节点,并返回指向节点的指针template <typename T>Node<T>* MyList<T>::at(int count){if (count > size){return NULL;}Node<T>* currentNode = first;int num = 1;while (num++ != count){currentNode = currentNode->next;}return currentNode;}//判空template <typename T>bool MyList<T>::isEmpty(){return size == 0;}#endif


主函数就不贴出来了,上面的函数经过测试,都能正常使用,代码风格不好,有待加强。


4.再一次写了链表,从大二到现在已经写了很多次链表了,但是每一次重新写都要在纸上写写画画很多才能写出来,而且可能有很多的细节没有考虑进去,但是比起大二,还是强了那么一点点,用笔和纸来帮助自己构造链表是最好不过的。




0 0
原创粉丝点击