C++單鏈表
一般很少使用單鏈表。在實際中,使用雙向鏈表居多,並定義一個頭尾指針變量,恆定指向頭尾節點,方便遍歷。
1.只有頭節點的情況
完整代碼如下:
// singlyLinkList.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <exception>
#include "linearList.h"
using namespace std;
template<class T>
struct chainNode
{
T element;
chainNode<T> * next;
chainNode(const T& element) {
this->element = element;
this->next = 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 insertToTail(const T& theElement);
void output() const;
int indexOfNode(chainNode<T>* theNode) const;
void checkIndex(int theIndex) const;
protected:
int listSize;
chainNode<T> * firstNode;
};
template<class T>
chain<T>::chain()
{
listSize = 0;
firstNode = NULL;
}
template<class T>
chain<T>::~chain()
{
chainNode<T> *node, *nextNode;
node = firstNode;
while (node) {
nextNode = node->next;
delete node;
node = nextNode;
}
}
template<class T>
bool chain<T>::empty() const
{
return listSize > 0;
}
template<class T>
int chain<T>::size() const
{
return listSize;
}
//給定index,查找節點
template<class T>
T & chain<T>::get(int theIndex) const
{
checkIndex(theIndex);
chainNode<T>* node = firstNode;
for (int i = 0; i < listSize; i++) {
if (i == theIndex)
break;
node = node->next;
}
return node->element;
}
//給定節點的值,查找index
template<class T>
int chain<T>::indexOf(const T & theElement) const
{
chainNode<T>* node = firstNode;
for (int i = 0; i < listSize; i++) {
if (node->element == theElement) {
return i;
}
node = node->next;
}
return -1;
}
//給定節點,查找index
template<class T>
int chain<T>::indexOfNode(chainNode<T>* theNode) const
{
chainNode<T>* node = firstNode;
int i = 0;
while (node) {
if (node->next == theNode) {
return i;
}
i++;
}
return -1;
}
//刪除一個節點,如果是雙向鏈表就沒有這麼麻煩了
template<class T>
void chain<T>::erase(int theIndex)
{
chainNode<T>* node = firstNode;
int i = 0;
while (node) {
if (i == (theIndex - 1)) {
break;
}
node = node->next;
i++;
}
if (node) {
chainNode<T>* tempNode = node->next;
node->next = tempNode->next;
delete tempNode;
}
}
//在指定的index處插入
template<class T>
void chain<T>::insert(int theIndex, const T& theElement) {
if ((theIndex < 0) || (theIndex > listSize)) {
throw "index must be in 0 to listSize";
}
if (!firstNode) {
firstNode = new chainNode<T>(theElement);
listSize++;
return;
}
if (theIndex == 0) {
chainNode<T>* node = new chainNode<T>(theElement);
node->next = firstNode;
firstNode = node;
}
else {
int i = 1;
chainNode<T>* node = firstNode;
while (node) {
if (i == theIndex) {
break;
}
i++;
node = node->next;
}
chainNode<T>* newNode = new chainNode<T>(theElement);
newNode->next = node->next;
node->next = newNode;
}
listSize++;
}
//在末尾插入
template<class T>
void chain<T>::insertToTail(const T& theElement)
{
chainNode<T>* node = firstNode;
while (node->next) {
node = node->next;
}
chainNode<T>* newNode = new chainNode<T>(theElement);
node->next = newNode;
listSize++;
}
//從Head開始輸出
template<class T>
void chain<T>::output() const
{
chainNode<T> *node = firstNode;
cout << "-------------" << endl;
while (node) {
cout << "node->element : " << node->element << endl;
node = node->next;
}
}
//檢查index是否越界
template<class T>
void chain<T>::checkIndex(int theIndex) const
{
if ((theIndex < 0) || (theIndex > listSize)) {
throw "out of index";
}
}
int main()
{
chain<int>* list = new chain<int>();
list->insert(0, 0);
list->insert(1, 111);
list->insert(2, 222);
list->insert(3, 333);
list->insert(0, 999);
list->insertToTail(1000);
list->output();
int index = list->indexOf(222);
cout << "index : " << index << endl;
cout << "get Index : " << list->get(3) << endl;
//------
list->erase(2);
list->output();
system("pause");
return 0;
}
linearList.h
#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 output() const = 0;
private:
};
運行結果:
2.添加尾節點指針
添加尾節點指針,方便節點的尾插入
...
protected:
...
chainNode<T> * lastNode; //指向鏈表的尾節點
//在末尾插入
template<class T>
void chain<T>::insertToTail(const T& theElement)
{
/*chainNode<T>* node = firstNode;
while (node->next) {
node = node->next;
}
chainNode<T>* newNode = new chainNode<T>(theElement);
node->next = newNode;
listSize++;*/
chainNode<T>* newNode = new chainNode<T>(theElement);
lastNode->next = newNode;
lastNode = newNode;
}
相應的,在任意位置插入節點的方法也要做改變,如下:
//在指定的index處插入
template<class T>
void chain<T>::insert(int theIndex, const T& theElement) {
if ((theIndex < 0) || (theIndex > listSize)) {
throw "index must be in 0 to listSize";
}
//頭節點不存在時,直接賦給頭尾節點
if (!firstNode) {
firstNode = new chainNode<T>(theElement);
lastNode = firstNode;
listSize++;
return;
}
//頭尾指向一個節點,表明鏈表只有一個節點,插入一個節點則將尾節點指向新節點即可
if (lastNode == firstNode) {
lastNode = new chainNode<T>(theElement);
firstNode->next = lastNode;
listSize++;
return;
}
if (theIndex == 0) {
chainNode<T>* node = new chainNode<T>(theElement);
node->next = firstNode;
firstNode = node;
}
else {
int i = 1;
chainNode<T>* newNode = new chainNode<T>(theElement);
chainNode<T>* node = firstNode;
while (node) {
if (i == theIndex) {
break;
}
i++;
node = node->next;
}
if (node->next) {
newNode->next = node->next;
node->next = newNode;
}
else { //尾節點
node->next = newNode;
lastNode = newNode;
}
}
listSize++;
}
其他代碼不變。