向量、链表、栈和队列

一、一点感想

自学数据结构和算法到现在时间也不短了,一直犹豫着要不要写一写向量等几个最最基本的数据结构,因为总觉得是最基本的,太容易了,不想花这个时间去写。然而学着学着慢慢发现,虽然这个很基本,但我并不一定能够做好(尤其是以前的我)。实际上我几次因为需要写过简单的结构,但是没有专门写过,而且体验也不是很好。最近在学图算法,里面涉及到一些更复杂的算法和结构,又时需要用上这几个基本数据结构作为辅助,于是我觉得,不如自己这次认真的写一下,作为模板放在电脑里,以后需要用向量什么的就用自己写的,这样可以帮助自己更好的理解数据结构。于是就有了现在的成果。
我觉得事情虽然简单,但是我还是很有收获的,因为以前是看上去简单,但是没有真正去做这件事,而现在我真正做了,完成了基本的工作,但是有的难点还是没有克服,比如遍历问题。这说明之前的认识有很大的错误,没有亲力亲为就以为自己懂了,那是无知的表现。从某种意义上讲,不断学习的目的之一就是为了克服这种无知,并且做到真正掌握知识和技术。讲这些基本的完成了,心里更有底了,以后在学习更难的内容的时候,我会更加清楚的知道自己以前做过什么工作,在使用数据结构的时候,也会有更好的掌控。

二、代码

1、Vector

#ifndef VECTOR__H__
#define VECTOR__H__
#include <cstdio>

template <typename T> class Vector
{
protected:	//受保护的成员外部是不可访问的 
	int size, N;
	T* a;
	void check_overflow();
	void check_underflow();
public:
	Vector();
	Vector(T e);
	Vector(T* a, int len);
	~Vector() { delete [] a; }
	void print() { print(0, N); }
	void print(int st, int end);
	int getSize() { return N; }
	T operator[](int id) { return a[id]; }
	void reverse();
	void insert(T e);
	void insert(int id, T e);
	T del(int id);
	T del() { return del(N - 1); }
};

template <typename T> Vector<T>::Vector()
{
	size = 1;
	N = 0;
	a = new T[size];
}

template <typename T> Vector<T>::Vector(T e)
{
	size = 2;
	N = 1;
	a = new T[size];
	a[0] = e;
}

template <typename T> Vector<T>::Vector(T *arr, int len)
{
	N = len;
	size = 2 * len;
	a = new T[size];
	for (int i = 0; i < len; i++) a[i] = arr[i];
}

template <typename T> void Vector<T>::insert(T e)
{
	check_overflow();
	a[N++] = e;
}

template <typename T> void Vector<T>::insert(int id, T e)
{
	check_overflow();
	for (int i = N; i > id; i++) a[i] = a[i - 1];
	++N;
	a[id] = e;
}

template <typename T> T Vector<T>::del(int id)
{
	T tmp = a[id];
	check_underflow();
	for (int i = id; i < N; i++) a[i] = a[i + 1];
	--N;
	return tmp;
}

template <typename T> void Vector<T>::print(int st, int end)
{
	printf("len : %d\n", end - st);
	for (int i = st; i < end; i++) printf("%d : %d\n", i, a[i]);
}

template <typename T> void Vector<T>::check_overflow()
{
	if (N + 1 > size)
	{
		size *= 2;
		T* tmp = new T[size];
		for (int i = 0; i < N; i++) tmp[i] = a[i];
		a = tmp;
	} 
}

template <typename T> void Vector<T>::check_underflow()
{
	if (N - 1 < size / 4)
	{
		size /= 2;
		T* tmp = new T[size];
		for (int i = 0; i < N; i++) tmp[i] = a[i];
		a = tmp; 
	}
}

template <typename T> void Vector<T>::reverse()
{
	int t = N / 2;
	for (int i = 0; i < t; i++) 
	{
		T tmp = a[i];
		a[i] = a[N - 1 -i];
		a[N - 1 -i] = tmp;
	}
}

#endif

2、 List

#ifndef LIST__H__
#define LIST__H__
#include <cstdio>

template <typename T>
struct node
{
	T data;
	node<T> * pred;
	node<T> * succ;
};

template <typename T> class List
{
	private:
		int N;
		node<T> *head;
		node<T> *tail;
		void init();
	public:
		List() { init(); }
		List(T e) { init(); insertAsLast(e); } 
		List(T * a, int len);
		node<T>* first() { return head->succ; }
		bool isEmpty() { return N == 0; }
		void insertAsLast(T e);
		void insertAsFirst(T e);
		void insert(T e) { insertAsLast(e); }
		T del() { delFirst(); }
		T delLast();
		T delFirst();
};

template <typename T> void List<T>::init()
{
	N = 0;
	head = new node<T>;
	tail = new node<T>;
	head->pred = NULL;
	head->succ = tail;
	tail->pred = head;
	tail->succ = NULL;
}

template <typename T> List<T>::List(T * a, int len)
{
	init();
	for (int i = 0; i < len; i++) insertAsLast(a[i]);
}


template <typename T> void List<T>::insertAsFirst(T e)
{
	N++;
	node<T> *nd = new node<T>;
	nd->data = e;
	nd->pred = head;
	nd->succ = head->succ;
	head->succ->pred = nd;
	head->succ = nd;
}

template <typename T> void List<T>::insertAsLast(T e)
{
	N++;
	node<T> *nd = new node<T>;
	nd->data = e;
	nd->pred = tail->pred;
	nd->succ = tail;
	tail->pred->succ = nd;
	tail->pred = nd;
}

template <typename T> T List<T>::delFirst()
{
	if (N)
	{
		N--;
		T tmp = head->succ->data;
		head->succ = head->succ->succ;
		head->succ->pred = head;
		return tmp;
	}
	else printf("Error! Empty! Cannot delete!");
}

template <typename T> T List<T>::delLast()
{
	N--;
	T tmp = tail->pred->data;
	tail->pred = tail->pred->pred;
	tail->pred->succ = tail;
	return tmp;
}

#endif 

3、Stack

自己在写的时候,由于对c++继承机制掌握不够熟练,陷入编译错误很久,主要在派生类的构造上。派生类的构造需要用初始化列表的方式给出基类的构造。

#ifndef STACK__H__
#define STACK__H__
#include "Vector.h"

template <typename T> class Stack: public Vector<T>
{
	public:
		Stack(): Vector<T>() { }
		Stack(T e): Vector<T>(e) { }
		Stack(T *a, int len): Vector<T>(a, len) { }
		void push(T e) { this->insert(this->getSize(), e); }
		T pop() { return this->del(); }
		T top() { return this->a[this->getSize() - 1]; }
};

#endif 

4、Queue

#ifndef QUEUE__H__
#define QUEUE__H__
#include "List.h"

template <typename T> class Queue: public List<T>
{
	public:
		Queue(): List<T>() { }
		Queue(T e): List<T>(e) { }
		Queue(T *a, int len): List<T>(a, len) {}
		void enqueue(T const& e) { this->insertAsLast(e); }
		T dequeue() { this->delFirst(); }
};

#endif

三、不足之处

  1. 这几个数据结构实现了基本的功能,但是API不算丰富,也许不能完全满足需求。由于我现在使用数据结构解决问题的经验很少,对哪些方法比较常用和重要没有直观的和深刻的理解,所以我想以后经验积累了、懂得了需求之后再来不断丰富自己的数据结构库,现在先到这里。
  2. 有的需求我是切身体会到了的,比如对链表实现遍历的功能,奈何自己能力不够,对c++的语法功能了解不够,尽管做了尝试但是还是没有成功。这个就需要以后自己越来越厉害、积累了知识之后再进行完善了。
  3. 诸如链表没有析构函数此类的不周到的地方,模板中到底有多少我也不知道。现在只把这些问题记录下来,等以后学了更多东西再来完善吧!

模板中的bug和代码缀余之处,都留给未来的自己好了。略略略。

原创文章 8 获赞 16 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Governor2601/article/details/84180554