雙向鏈表
工作中使用比較多,插入節點方式一般使用尾插入以達到節點的順序性,在指定位置插入節點使用較少。
遍歷的時候,我是採用二分法,靠近頭節點的,從頭節點開始遍歷,靠近尾節點的,從尾節點開始遍歷,效率小於O(n)。
我是基於上個單鏈表的文章進行優化修改的,直接貼代碼:
// doublyLinkedList.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "linearList.h"
using namespace std;
template<class T>
struct chainNode
{
T element;
chainNode<T>* next;
chainNode<T>* prev;
chainNode<T>(const T& element) {
this->element = element;
this->next = this->prev = NULL;
}
};
template<class T>
class chain : public linearList<T>
{
public:
chain();
~chain();
bool empty() const;
int size() const;
T& get(int theIndex) const;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
void pushBack(const T& theElement);
void output() const;
bool init(chainNode<T>* newNode);
chainNode<T>* travering(int theIndex) const;
protected:
int listSize;
chainNode<T> * headNode;
chainNode<T> * tailNode;
};
template<class T>
chain<T>::chain()
{
listSize = 0;
headNode = tailNode = NULL;
}
template<class T>
chain<T>::~chain()
{
chainNode<T> *node, *nextNode;
node = headNode;
while (node) {
nextNode = node->next;
delete node;
node = nextNode;
}
}
//初始化
template<class T>
bool chain<T>::init(chainNode<T>* newNode)
{
//頭尾指針爲空
if (!headNode) {
headNode = newNode;
tailNode = newNode;
listSize++;
return false;
}
//頭尾指針指向一個節點,鏈表中只有一個節點
if (headNode == tailNode) {
tailNode->next = newNode;
tailNode = newNode;
tailNode->prev = headNode;
headNode->next = tailNode;
headNode->prev = tailNode->next = NULL;
listSize++;
return false;
}
return true;
}
//根據index遍歷找到對應節點 O(n/2)
template<class T>
chainNode<T>* chain<T>::travering(int theIndex) const
{
chainNode<T>* node;
if (theIndex <= listSize / 2) {
node = headNode;
int i = 0;
while (node) {
if (theIndex == i) {
break;
}
node = node->next;
i++;
}
}
else {
node = tailNode;
int i = listSize - 1;
while (node) {
if (theIndex == i) {
break;
}
node = node->prev;
i--;
}
}
return node;
}
template<class T>
bool chain<T>::empty() const
{
return listSize <= 0;
}
template<class T>
int chain<T>::size() const
{
return listSize;
}
template<class T>
T & chain<T>::get(int theIndex) const
{
if ((theIndex < 0) || (theIndex > listSize - 1)) {
throw "out of index for list";
}
chainNode<T>* node = travering(theIndex);
return node->element;
}
template<class T>
int chain<T>::indexOf(const T & theElement) const
{
return 0;
}
//刪除
template<class T>
void chain<T>::erase(int theIndex)
{
if ((theIndex < 0) || (theIndex > listSize - 1)) {
throw "out of index for list";
}
chainNode<T>* node = travering(theIndex);
node->prev->next = node->next;
node->next->prev = node->prev;
delete node;
}
//給定index插入
template<class T>
void chain<T>::insert(int theIndex, const T & theElement)
{
chainNode<T>* newNode = new chainNode<T>(theElement);
//檢查是否初始化了頭尾指針
if (!init(newNode)) {
return;
}
if (theIndex < 0) {
theIndex = 0;
}
if (theIndex > listSize) {
theIndex = listSize;
}
//theIndex是頭插入
if (theIndex == 0) {
newNode->next = headNode;
headNode->prev = newNode;
headNode = newNode;
listSize++;
return;
}
//theIndex是尾插入
if (theIndex == listSize) {
newNode->prev = tailNode;
tailNode->next = newNode;
tailNode = newNode;
listSize++;
return;
}
//其他
chainNode<T>* node = travering(theIndex);
newNode->next = node->next;
newNode->prev = node;
node->next->prev = newNode;
node->next = newNode;
listSize++;
}
//尾插入
template<class T>
void chain<T>::pushBack(const T & theElement)
{
chainNode<T>* newNode = new chainNode<T>(theElement);
//檢查是否初始化了頭尾指針
if (!init(newNode)) {
return;
}
//在尾指針後面插入,並將尾指針後移
tailNode->next = newNode;
newNode->prev = tailNode;
tailNode = newNode;
listSize++;
}
template<class T>
void chain<T>::output() const
{
chainNode<T>* node = headNode;
cout << "-----------" << endl;
int i = 0;
while (node) {
cout << "index: " << i << "->" << node->element << endl;
node = node->next;
i++;
}
}
main方法如下:
int main()
{
chain<int>* list = new chain<int>();
list->pushBack(0);
list->insert(0, 0);
list->pushBack(222);
list->pushBack(333);
list->insert(0, 999);
list->insert(10, 444);
list->output();
cout << "get: " << "index = " << 4 << "->" << list->get(4) << endl;
list->erase(3);
list->output();
list->~chain();
system("pause");
return 0;
}
linearList.h中的抽象類linearList如下:
#pragma once
template<class T>
class linearList
{
public:
virtual ~linearList() {};
virtual bool empty() const = 0;
virtual int size() const = 0;
virtual T& get(int theIndex) const = 0;
virtual int indexOf(const T& theElement) const = 0;
virtual void erase(int theIndex) = 0;
virtual void insert(int theIndex, const T& theElement) = 0;
virtual void pushBack(const T& theElement) = 0;
virtual void output() const = 0;
private:
};