最近学习了数据结构的一些知识,了解的一下单链表的实现。本文中用类的方式构建节点和链表,未来以后方便使用,直接构建模板类。
首先实现节点的构建
template<typename T> class Node { public: T element; Node<T> *next; Node() { next = NULL; } Node(T element) { this->element = element; next = NULL; } };
之后就是的单链表的类和功能函数,链表类里面设有私有成员有链表头head,链表尾tail,链表长度size。
template<typename T> class LinkedList { public: LinkedList(); ~LinkedList(); void addFirst(T element); void addLast(T element); T getFirst(); T getLast(); T removeFirst(); T removeLast(); void add(T element); void add(int index, T element); void clear(); T get(int index); int indexOf(T element); bool isEmpty(); T removeAt(int index); private: Node<T> *head, *tail; int size; };
接下来实现链表类里的每个功能函数
(1)单链表初始化,构造函数
template<typename T> LinkedList<T>::LinkedList() { head = tail = NULL; size = 0; }
(2)实现析构函数
template<typename T> LinkedList<T>::~LinkedList() {}
(3)插入元素到链表头节点,这里需要注意判断(链表是否为空)尾节点是否为空,如果为空,则将尾节点指向头节点。,size++。
template<typename T> void LinkedList<T>::addFirst(T element) { Node<T> *newNode = new Node<T>; newNode->next = head; head = newNode; size++; if (tail = NULL) tail = head; }
(4)插入元素到链表尾节点,如果链表为空,则把头节点和尾节点一起指向新插入的节点,如果非空,则将尾节点的下一节点指向新插入的节点,然后尾节点再指向尾节点的下一节点,size++。
template<typename T> void LinkedList<T>::addLast(T element) { if (tail == NULL) head = tail = new Node<T>(element); else { tail->next = new Node<T>(element); tail = tail->next; } size++; }
(5)取链表头元素,增加空链表判断
template<typename T> T LinkedList<T>::getFirst() { if (size == 0) throw runtime_error("Index out of range"); else { return head->element; } }
(6)取链表尾节点元素,同样空链表判断
template<typename T> T LinkedList<T>::getLast() { if (size == 0) throw runtime_error("Index out of range"); else { return tail->element; } }
(7)移除链表头节点,这里首先进行空链表判断,之后在申请一个临时节点指向头节点,头节点指向头节点的下一个节点,之后返回头节点元素,释放临时节点。
template<typename T> T LinkedList<T>::removeFirst() { if (head == 0) throw runtime_error("No elements in the list"); else { Node<T> *temp = head; head = head->next; if (head == NULL) tail = NULL; T element = temp->element; size--; delete temp; return element; } }
(8)删除尾节点,尾节点的删除操作比较麻烦,首先判断是否为空链表,若空,则报错,若为一个元素的链表,申请临时节点指向头节点,之后直接将头节点和尾节点置为NULL。若链表size大于1,那么current指向尾节点的前一个节点,申请临时节点指向尾节点,尾节点指向current节点,tail->next置空,删除临时节点。
template<typename T> T LinkedList<T>::removeLast() { if (size == 0) throw runtime_error("No elements in the list"); else if (size == 1) { Node<T> *temp = head; head = tail = NULL; size = 0; T element = temp->element; delete temp; return element; } else { Node<T> *current = head; for (int i = 1; i < size - 1; i++) curent = current->next; Node<T> *temp = tail; tail = current; tail->next = NULL; size--; T element = temp->element; delete temp; return element; } }
(9)指点位置插入节点,先申请标记节点current标记到插入节点的前一节点,之后设置temp为current的下一节点,设置current的下一节点为插入节点。
template<typename T> void LinkedList<T>::add(int index, T element) { if (index == 0) addFirst(element); else if (index >= size) addLast(element); else { Node<T> *current = head; for (int i = 1; i < index; i++) current = current->next; Node<T> *temp = current->next; current->next = new Node<T>(element); current->next->next = temp; size++; } }
(10)移除指定位置的元素
template<typename T> T LinkedList<T>::removeAt(int index) { if (index < 0 || index >= size) throw runtime_error("Index out of range"); else if (index == 0) removeFirst(); else if (index = size - 1) removeLast(); else { Node<T> *previous = head; for (int i = 1; i < index; i++) { previous = previous->next; } Node<T> *temp = previous->next; previous->next = temp->next; size--; T element = temp->next; delete temp; return element; } }