C++雙向鏈表

雙向鏈表

工作中使用比較多,插入節點方式一般使用尾插入以達到節點的順序性,在指定位置插入節點使用較少。

遍歷的時候,我是採用二分法,靠近頭節點的,從頭節點開始遍歷,靠近尾節點的,從尾節點開始遍歷,效率小於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:

};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章