之前一直都是用的Java学习的数据结构,这里把自己学习C++时用C++实现数据结构之单链表的代码直接贴出来,以供参考,还有很多可以改进之处,就不那么纠结了,作为学习数据结构的C++代码实现,应该是足够了。
编码的格式规范是Java的,个人觉得这种范式更加清晰明了。
调试环境是VS2013及VC++6.0,均全部通过。
///////////////////////单链表///////////////////////////////
/*
SingleLinkedList.h文件:用于定义单链表的节点及方法
*/
using namespace std;
///////表示单链表中节点的结构体///////////////////////////////////////////////////////////////////////////////////
template //用函数模板的原因是:链表节点中存储的数据类型不确定
class Node{
public:
/*节点存储的数据*/
T element;
/*指向下一个节点的指针*/
Node *next;
public:
/*空构造器*/
Node(){}
/*构造器*/
Node(T e){
element = e;
}
};
////////////////////////////单链表类的定义////////////////////
template
class SingleLinkedList{
private:
/*链表长度,存储的结点个数*/
int size;
/*表头节点,节点中存储的数据的类型为T*/
Node *head;
/*获取链表中指定索引上的节点,仅供内部调用*/
Node* node(int index);
public:
/*构造器*/
SingleLinkedList();
/*析构函数*/
~SingleLinkedList();
/*获取链表长度,即当前链表中结点的个数*/
int length();
/*检查索引范围*/
bool checkIndex(int index);
/*添加指定的数据到链表尾部*/
bool insert(T element);
/*添加指定的数据到指定的索引位置*/
bool insert(int index, T element);
/*删除指定位置上的数据*/
bool remove(int index);
/*获取指定索引上的数据*/
T get(int index);
/*获取指定数据的索引,不存在时返回0*/
int getIndex(T element);
/*将指定位置的数据修改为给定的数据element*/
void set(int index, T element);
/*打印整个链表*/
void print();
/*释放整个链表*/
void freeList();
};
///////////////////////SingleLinkedList.cpp////////////////
/*
包含测试代码的main()函数,放在了.cpp文件的最后。一般而言,单独写成一个test.cpp会更好点。
*/
#include
#include
#include "SingleLinkedList.h"
using namespace std;
/*
构造器
*/
template<typename T>
SingleLinkedList::SingleLinkedList(){
this->head = new Node();//调用默认构造器
this->size = 0;//初始化长度为0
this->head->next = NULL;
}
template<typename T>
SingleLinkedList::~SingleLinkedList(){
}
/*
获取链表长度,即当前链表中结点的个数
@return 链表的大小
*/
template<typename T>
int SingleLinkedList::length(){
return this->size;
}
/*
检查索引范围
@param index 索引
@return 索引合法,则返回true;否则,返回false
*/
template<typename T>
bool SingleLinkedList::checkIndex(int index){
return index >= 0 && index <= size;
}
/*
获取指定索引上的节点
@param index 给定的索引
@return 节点对象
*/
template<typename T>
Node* SingleLinkedList::node(int index){
checkIndex(index);
Node* n = this->head;
for (int i = 0; i < index; i++){
n = n->next;
}
return n;
}
/*
添加指定的数据到链表尾部
@param element 需要添加到链表尾位的数据
@return 添加成功,返回true;否则,返回false
*/
template<typename T>
bool SingleLinkedList::insert(T element){
Node* newNode = new Node(element);//构造节点对象
//如果链表是空
if (this->size == 0){
this->head = newNode;
}
//链表非空
Node* temp = this->head;
while (temp->next != NULL){//从头节点开始,找到最后一个节点,判断条件中必须是n->next,而不能是n
temp = temp->next;
}
temp->next = newNode;
newNode->next = NULL;//这句不可少
size++;
return true;
}
/*
添加指定的数据到指定的索引位置
@param index 指定的索引位置
@param element 将要插入的数据
@return 插入数据成功,返回true;否则,返回false
*/
template<typename T>
bool SingleLinkedList::insert(int index, T element){
checkIndex(index);
Node* newNode = new Node(element);
if (index == 0){//插入新节点作为链表头节点
newNode->next = this->head;
this->head = newNode;
}
else if (index == size){//插入新节点作为尾部节点
insert(element);
}
else{//插入位置新节点到index索引之上
//获取index索引上的节点
Node* nIndex_pre = node(index - 1);//获取index-1位置上的节点
Node* nIndex = node(index);//获取index索引上的节点
nIndex_pre->next = newNode;
newNode->next = nIndex;
}
size++;
return true;
}
/*
打印整个链表
*/
template<typename T>
void SingleLinkedList::print(){
//如果链表为空
if (NULL == this->head){
cout << "This list is empty.";
return;//结果方法运行,下面的代码不再执行
}
//链表不为空
Node* n = this->head;
while (NULL != n){//此处的判断条件中,只能是n,而不能用n->next
cout << n->element << ",";
n = n->next;
}
cout << '\n';//换行
}
/*
获取指定索引上的数据
@param index 给定的索引
@return 指定索引上的数据
*/
template<typename T>
T SingleLinkedList::get(int index){
return node(index)->element;
}
/*
获取指定数据的索引,不存在时返回0
@param element 给定的需要查找索引的数据
@return 给定数据在链表中的索引(第一次出现)
*/
template<typename T>
int SingleLinkedList::getIndex(T element){
bool flag = true;
Node* n = this->head;
int index = 0;
while (flag && (NULL != n)){
if (n->element == element){
flag = false;
}
n = n->next;
index++;
}
if (index > size){
return -1;//没找到
}
return index - 1;//减1,是因为"index++;",在找到相等数据后,仍然被执行了一次,就是多走了一次
}
/*
删除指定位置上的数据
@param index 给定的索引
@return 删除成功,返回true;否则,返回false
*/
template<typename T>
bool SingleLinkedList::remove(int index){
checkIndex(index);
if (index == 0){//删除是头节点
Node* nHead = this->head;
Node* nHead_next = nHead->next;
this->head = nHead_next;
}
else if (index == size){//删除的是链表最后一个节点
Node* nIndex_pre = node(index - 1);
nIndex_pre->next = NULL;
}
else{//删除的是中间节点
Node* nPre = node(index - 1);
Node* nNext = node(index + 1);
nPre->next = nNext;
}
size--;
return true;
}
/*
将指定位置的数据修改为给定的数据element
@param index 指定的索引
@param element 给定的数据
*/
template<typename T>
void SingleLinkedList::set(int index, T element){
checkIndex(index);
Node* n = node(index);
n->element = element;
}
/*
释放整个链表:将链表所有节点在内存中占据的存储空间释放
*/
template<typename T>
void SingleLinkedList::freeList(){
/*for (Node* n = this->head; n->next != NULL; n = n->next){
delete n;
}*/
//上面那种释放方式行不通的原因在于:释放一个head后,就断链了,再也找不到之后的节点了
Node* n1 = this->head, *n2;
while (NULL != n1){
n2 = n1->next;
delete n1;
n1 = n2;
}
}
int main(){
SingleLinkedList<int> list;
cout << list.checkIndex(-1) << endl;
list.insert(1);
list.insert(12);
list.insert(22);
list.insert(1, 10);
list.print();
cout << list.length() << endl;
cout << list.get(1) << endl;
cout << list.getIndex(10) << endl;
list.remove(1);
cout << list.length() << endl;
list.print();
list.set(1, 111);
cout << list.length() << endl;
list.print();
list.freeList();
return 0;
}