工作之后很少再从头开始实现基础数据结构,最近试着写一写,发现还是有很多知识只能在写的过程中才能去体会,而不是想当然的认为造个轮子就是依葫芦画瓢了。一些细节上的处理,不管是数据结构本身的知识点,还是语言语法本身的知识点同样也只能在写的过程中才能更好的理解和把握。
废话不多说,C++实现一个list模板。
数据结构最重要的四个特征:增、删、查、改。这里没有实现改的api,主要是因为对于list而言,“改”并不是很重要。
#include<iostream>
#include<errno.h>
#include<typeinfo>
#include<exception>
#include<cctype>
#include<unistd.h>
template<typename T>
struct node
{
T data;
struct node* next;
};
template<typename T>
class List
{
private:
struct node<T>* head;
struct node<T>* last;
struct node<T>* tmp;
public:
explicit List(){
this->head = NULL;
}
~List(){
destroy_list();
}
private:
void init_list(const T& d){
this->head = new node<T>;
this->head->data = d;
this->head->next = NULL;
this->tmp = this->head;
this->last = head;
}
node<T>* get_head(){
return this->head;
}
void destroy_list(){
this->tmp = this->head;
struct node<T>* tmp_node = tmp;
while(this->tmp){
tmp_node = this->tmp->next;
delete this->tmp;
this->tmp = tmp_node;
}
}
public:
bool is_empty(){
return this->head?false:true;
}
bool is_exist(const T& d){
bool is_ = false;
struct node<T>* node = find_node(d);
node? is_ = true: is_ = false;
return is_;
}
void push_back_node(const T& d){
if(typeid(d) != typeid(int)) throw std::exception::exception("type is not correct!");
if(this->head){
this->tmp = new node<T>;
this->tmp->data = d;
this->tmp->next = NULL;
this->last->next = tmp;
this->last = this->tmp;
}
else{
init_list(d);
}
}
void pop_back_node(){
struct node<T>* tmp_node = this->head;
if(this->is_empty()) return;
while(tmp_node->next != this->last){
std::cout<<" tmp = "<<tmp_node->data<<std::endl<<std::flush;
tmp_node = tmp_node->next;
}
if(!this->last) throw std::exception::exception("Oops,something wrong!");
//caution tmp_node->next must be set NULL before delete this->last, because tmp_node->next is the same as this->last
tmp_node->next = NULL;
delete this->last;
this->last = tmp_node;
}
void display_node(){
int i = 0;
this->tmp = this->head;
while(this->tmp){
std::cout<<"node "<<i++<<" = "<<this->tmp->data<<std::endl;
this->tmp = this->tmp->next;
}
}
void delete_node(const T& d){
struct node<T>* priv_node;
struct node<T> * tmp_node;
struct node<T> * next_node;
if(!is_exist(d)) return;
if(this->head->data == d){
if(!this->head->next){
delete this->head;
this->head = NULL;
this->tmp = NULL;
this->last = NULL;
return;
}
else{
this->tmp = this->head->next;
delete this->head;
this->head = this->tmp;
this->tmp = this->head;
return;
}
}
priv_node = find_priv_node(d);
if(!priv_node) return;
tmp_node = priv_node->next;
if(!tmp_node) throw std::exception::exception("Oops,something wrong!");
next_node = tmp_node->next;
priv_node->next = next_node;
delete tmp_node;
return;
}
size_t get_size(){
size_t size = 0;
this->tmp = this->head;
while(tmp){
tmp = tmp->next;
size++;
}
return size;
}
private:
struct node<T>* find_node(const T& d){
this->tmp = this->head;
while(this->tmp){
if(this->tmp->data == d) return tmp;
else this->tmp = this->tmp->next;
}
return NULL;
}
struct node<T>* find_priv_node(const T& d){
struct node<T>* front_node = this->head;
struct node<T>* rear_node = this->head;
if(front_node->data == d) return NULL;
while(rear_node->next){
front_node = rear_node;
rear_node = rear_node->next;
if(rear_node->data == d) return front_node;
}
return NULL;
}
};
int main()
{
std::cout<<"---start----"<<std::endl;
List<int> l;
l.push_back_node(3);
l.push_back_node(4);
l.push_back_node(5);
l.push_back_node(6);
l.push_back_node(7);
l.push_back_node(8);
l.display_node();
std::cout<<" 4 is exist ? --> "<<l.is_exist(4)<<std::endl;
std::cout<<" 9 is exist ? --> "<<l.is_exist(9)<<std::endl;
std::cout<<" size = "<<l.get_size()<<std::endl;
l.delete_node(6);
l.display_node();
std::cout<<"---------------"<<std::endl;
l.delete_node(3);
l.display_node();
std::cout<<"---------------"<<std::endl;
l.push_back_node(100);
l.push_back_node(200);
l.push_back_node(100);
l.display_node();
std::cout<<"---------------"<<std::endl;
l.delete_node(100);
l.display_node();
std::cout<<"---------------"<<std::endl;
l.delete_node(100);
l.display_node();
std::cout<<"---------------"<<std::endl;
List<std::string> l1;
l1.push_back_node("xujiwei");
l1.push_back_node("hello");
l1.push_back_node("world");
l1.display_node();
l1.delete_node("xujiwei");
l1.display_node();
l1.pop_back_node();
l1.display_node();
return 0;
}