前言
本文主要记录数据结构中的单向链表、双向链表C++实现以及要点等。
代码
原理就不说了,基础中的基础。直接上代码:
首先是CNode.h文件:
#ifndef _NODE_H__
#define _NODE_H__
class CNode{
private:
int data;
CNode *nextNode;
public:
CNode();
void setData(int iData);
int getData() const;
void setNextNode(CNode *nextNode);
CNode* getNextNode() const;
};
#endif
接下来是SingleLinkedList.h文件
#ifndef _SINGLE_LINKEDLIST_H__
#define _SINGLE_LINKEDLIST_H__
#include "CNode.h"
class SingleLinkedList{
private:
CNode *firstNode;
public:
SingleLinkedList();
~SingleLinkedList();
void insertAtTheFront(int data);
void insertInTheMiddle(int data, int position);
void insertAtTheEnd(int data);
void deleteFromTheFront();
void deleteFromTheMiddle(int position);
void deleteFromTheEnd();
bool search(int data);
void display();
};
#endif
然后就是源文件。其中,为了图方便,双向链表的结点和链表类我直接写在源文件里了。
#include <iostream>
#include "CNode.h"
#include "SingleLinkedList.h"
using namespace std;
CNode::CNode(){
this->nextNode = NULL;
};
void CNode::setData(int iData){
this->data = iData;
};
int CNode::getData() const{
return data;
}
void CNode::setNextNode(CNode *nextNode){
this->nextNode = nextNode;
};
CNode* CNode::getNextNode() const{
return nextNode;
};
SingleLinkedList::SingleLinkedList(){
firstNode = NULL;
cout << "SUCCESSFULLY BUILD" << endl;
};
SingleLinkedList::~SingleLinkedList(){
};
void SingleLinkedList::insertAtTheFront(int data){
CNode *p = new CNode;
p->setData(data);
if (firstNode == NULL) {
firstNode = new CNode;
this->firstNode->setData(data);
}
else {
p->setNextNode(firstNode);
this->firstNode = p;
}
};
void SingleLinkedList::insertInTheMiddle(int data, int position){
CNode *p = firstNode;
CNode *s = new CNode;
s->setData(data);
if (firstNode == NULL) {
firstNode = new CNode;
this->firstNode->setData(data);
return;
}
if (position == 1){
insertAtTheFront(data);
return;
}
for (int i = 0; i < position - 2; i++){
if (p->getNextNode() != NULL) p = p->getNextNode();
else {
cout << "ERROR";
return;
}
}
s->setNextNode(p->getNextNode());
p->setNextNode(s);
};
void SingleLinkedList::insertAtTheEnd(int data){
CNode *p = firstNode;
CNode *s = new CNode;
s->setData(data);
while (p->getNextNode() != NULL){
p = p->getNextNode();
}
p->setNextNode(s);
/*
CNode *p = firstNode;
CNode s;
s.setData(data);
while (p->getNextNode() != NULL){
p = p->getNextNode();
}
p->setNextNode(&s);
*/
};
void SingleLinkedList::deleteFromTheFront(){
if (firstNode == NULL) return;
else if (firstNode->getNextNode() == NULL){
firstNode = NULL;
return;
}
CNode *p = firstNode->getNextNode();
firstNode = p;
};
void SingleLinkedList::deleteFromTheMiddle(int position){
CNode *p = firstNode;
CNode *s = new CNode;
if (firstNode == NULL) return;
if (position == 1){
deleteFromTheFront();
return;
}
for (int i = 0; i < position - 2; i++){
if (p->getNextNode() != NULL) p = p->getNextNode();
else {
cout << "Error Position"<<endl;
return;
}
}
p->setNextNode(p->getNextNode()->getNextNode());
};
void SingleLinkedList::deleteFromTheEnd(){
CNode *p = firstNode;
if (p == NULL) return;
if (p->getNextNode() == NULL){
firstNode = NULL;
return;
}
while (p->getNextNode()->getNextNode() != NULL) p = p->getNextNode();
p->setNextNode(NULL);
};
bool SingleLinkedList::search(int data){
CNode *p = firstNode;
if (p == NULL) return false;
while (p->getNextNode() != NULL){
if (p->getData() == data) return true;
p = p->getNextNode();
}
if (p->getData() == data) return true;
else return false;
};
void SingleLinkedList::display(){
CNode *p = firstNode;
if (firstNode == NULL)return;
int i = 0;
while (p->getNextNode() != NULL){
cout << ++i << ":" << p->getData() << endl;
p = p->getNextNode();
}
cout << ++i << ":" << p->getData() << endl;
};
class DNode{
private:
int data;
DNode *preNode;
DNode *nextNode;
public:
DNode(){
this->preNode = NULL;
this->nextNode = NULL;
};
void setData(int iData){
data = iData;
};
int getData() const{
return data;
};
void setNextNode(DNode *nextNode){
this->nextNode = nextNode;
};
void setPreNode(DNode *preNode){
this->preNode = preNode;
};
DNode* getPreNode() const{
return preNode;
};
DNode* getNextNode() const{
return nextNode;
};
};
class DLL{
private:
DNode *firstNode;
DNode *lastNode;
public:
DLL(){
firstNode = NULL;
lastNode = NULL;
cout << "SUCCESSFULLY BUILD" << endl;
};
~DLL(){
};
void insertAtTheFront(int data){
DNode *p = new DNode;
p->setData(data);
if (firstNode == NULL) {
firstNode = new DNode;
this->firstNode->setData(data);
this->lastNode = firstNode;
}
else {
p->setNextNode(firstNode);
firstNode->setPreNode(p);
this->firstNode = p;
}
};
void insertInTheMiddle(int data, int position){
if (position <= 1){
cout << "ERROR" << endl;
return;
}
DNode *p = firstNode;
DNode *s = new DNode;
s->setData(data);
for (int i = 0; i < position - 2; i++){
if (p->getNextNode() != NULL) p = p->getNextNode();
else cout << "ERROR";
}
p->getNextNode()->setPreNode(s);
s->setNextNode(p->getNextNode());
s->setPreNode(p);
p->setNextNode(s);
cout << "SUCCESS" << endl;
};
void insertAtTheEnd(int data){
DNode *p = new DNode;
p->setData(data);
p->setPreNode(lastNode);
lastNode->setNextNode(p);
lastNode = p;
};
void deleteFromTheFront(){
//empty list
if (firstNode == NULL){
cout << "ERROR" << endl;
return;
}
//only 1 node
else if (firstNode->getNextNode() == NULL){
cout << "ERROR" << endl;
return;
}
DNode *p = firstNode->getNextNode();
firstNode = p;
};
void deleteFromTheMiddle(int data){
DNode *p = firstNode;
DNode *s =new DNode;
while (p->getNextNode() != NULL){
if (p->getNextNode()->getData() == data){
if (p->getNextNode()->getNextNode() == NULL){
return;
}
s = p->getNextNode()->getNextNode();
p->setNextNode(s);
s->setPreNode(p);
}
else p = p->getNextNode();
};
}
void deleteFromTheEnd(){
if (lastNode == NULL){
cout << "ERROR" << endl;
return;
}
else if (firstNode == lastNode){
cout << "ERROR" << endl;
return;
}
lastNode = lastNode->getPreNode();
lastNode->setNextNode(NULL);
cout << "SUCCESS" << endl;
};
bool search(int data){
DNode *p = firstNode;
while (p->getNextNode() != NULL){
if (p->getData() == data) return true;
p = p->getNextNode();
}
if (p->getData() == data) return true;
else return false;
};
void display(){
DNode *p = firstNode;
int i = 0;
while (p->getNextNode() != NULL){
cout << ++i << ":" << p->getData() << endl;
p = p->getNextNode();
}
cout << ++i << ":" << p->getData() << endl;
};
void invertdis(){
DNode *p = lastNode;
int i = 0;
while (p->getPreNode() != NULL){
cout << ++i << ":" << p->getData() << endl;
p = p->getPreNode();
}
cout << ++i << ":" << p->getData() << endl;
}
};
int main(){
SingleLinkedList a;
DLL b;
int mod = 0;
int flag = 0;
int value, index;
int temp;
cout << "Input number to choose the mode" << endl;
cout << "1 for singlelinkedlist" << endl;
cout << "2 for doublylinkedlist" << endl;
cin >> temp;
if (temp == 1){
a.insertAtTheFront(1);
a.insertAtTheFront(10);
a.insertAtTheFront(100);
a.display();
while (1){
cout << "Input 1 to insert at the front;" << endl;
cout << "Input 2 to insert at the middle;" << endl;
cout << "Input 3 to insert at the end;" << endl;
cout << "Input 4 to delete at the front;" << endl;
cout << "Input 5 to delete at the middle;" << endl;
cout << "Input 6 to delete at the end;" << endl;
cout << "Input 7 to search;" << endl;
cout << "Input 0 to quit;" << endl;
cin >> mod;
switch (mod){
case 0:flag = 1; break;
case 1:cin >> value; a.insertAtTheFront(value); break;
case 2:cin >> value >> index; a.insertInTheMiddle(value, index); break;
case 3:cin >> value; a.insertAtTheEnd(value); break;
case 4:a.deleteFromTheFront(); break;
case 5:cin >> value; a.deleteFromTheMiddle(value); break;
case 6:a.deleteFromTheEnd(); break;
case 7:cin >> value; if (a.search(value))cout << "YES" << endl; else cout << "NO" << endl; break;
}
a.display();
if (flag == 1) break;
}
cout << "finish" << endl;
}
else if (temp == 2){
b.insertAtTheFront(1);
b.insertAtTheFront(10);
b.insertAtTheFront(100);
b.display();
while (1){
cout << "Input 1 to insert at the front;" << endl;
cout << "Input 2 to insert at the middle;" << endl;
cout << "Input 3 to insert at the end;" << endl;
cout << "Input 4 to delete at the front;" << endl;
cout << "Input 5 to delete at the middle;" << endl;
cout << "Input 6 to delete at the end;" << endl;
cout << "Input 7 to search;" << endl;
cout << "Input 8 to invert display;" << endl;
cout << "Input 0 to quit;" << endl;
cin >> mod;
switch (mod){
case 0:flag = 1; break;
case 1:cin >> value; b.insertAtTheFront(value); b.display(); break;
case 2:cin >> value >> index; b.insertInTheMiddle(value, index); b.display(); break;
case 3:cin >> value; b.insertAtTheEnd(value); b.display(); break;
case 4:b.deleteFromTheFront(); b.display(); break;
case 5:cin >> value; b.deleteFromTheMiddle(value); b.display(); break;
case 6:b.deleteFromTheEnd(); b.display(); break;
case 7:cin >> value; if (b.search(value))cout << "YES" << endl; else cout << "NO" << endl; b.display(); break;
case 8:b.invertdis(); break;
}
if (flag == 1) break;
}
cout << "finish" << endl;
}
else {
cout << "ERROR!" << endl;
}
}
随手写的,BUG可能不少,如若出现,还望海涵并指正。
其中,单链表的删除是删除指定位置上的数值,双链表的删除是删除链表中的所有该值。
注意点
1 函数内对象的析构
void SingleLinkedList::insertAtTheEnd(int data){
CNode *p = firstNode;
CNode *s = new CNode;
s->setData(data);
while (p->getNextNode() != NULL){
p = p->getNextNode();
}
p->setNextNode(s);
/*
CNode *p = firstNode;
CNode s;
s.setData(data);
while (p->getNextNode() != NULL){
p = p->getNextNode();
}
p->setNextNode(&s);
*/
};
我个人觉得被注释掉的内容和正在运行的部分是一样的,但这么运行其实不行。
个人的猜想是函数内的对象在函数结束后需要被析构有关系,经过一番费力地查找,果然如此。顺便该文章对指针的讲解也是挺细致的:
指针
对于指针p,q来说,一旦有p=q,那么对p的所有更改都会在q上也进行更改。这是在实现链表、栈、队列时的原理所在,即定义指针p=front,不断通过媒介指针p=p->getNextNode()遍历链表找到末尾,再把新的结点挂到p上或者删除最后的结点p。
2 初始化
CNode::CNode(){
this->nextNode = NULL;
};
和JAVA不同,C++中没有初始化是不会自动设置缺省值为NULL的,就不能直接用判断来看nextNode是不是NULL。需要尤其注意。