数据结构——线性表:顺序表、单链表、双链表(C++)

内容概要:​​​​​​​

1.代码部分:

  • 线性表抽象类
  • 顺序表类
  • 单链表类
  • 双链表类
  • 主函数

2.基本概念及注意事项


代码(测试环境VS2017):

//线性表ADT类的定义:ADT_List.h

template <typename E>class List
{
private:
	void operator=(const List&) {}
	List(const List&) {}
public:
	List() {}
	virtual ~List(){}

	virtual void clear() = 0;
	virtual void insert(const E&item) = 0;
	virtual void append(const E&item) = 0;
	virtual E remove() = 0;
	virtual void moveToStart() = 0;
	virtual void moveToEnd() = 0;
	virtual void prev() = 0;
	virtual void next() = 0;
	virtual int length() const = 0;
	virtual int currPos()const = 0;
	virtual void moveToPos(int pos) = 0;
	virtual const E& getValue()const = 0;
};
//顺序表类的实现:ADT_List.h

template<typename E>
class AList :public List<E>
{
private:
	int maxSize;
	int listSize;
	int curr;
	E*listArry;
public:
	AList(int size = 100)//构造,默认大小为100
	{
		maxSize = size;
		listSize = curr = 0;
		listArry = new E[maxSize];
	}
	~AList() { delete[]listArry; }

	void clear()
	{
		delete[]listArry;
		listSize = curr = 0;
		listArry = new E[maxSize];
	}
	void insert(const E&it)
	{
		assert(listSize < maxSize);
		for (int i = listSize; i > curr; i--)
			listArry[i] = listArry[i - 1];
		listArry[curr] = it;
		listSize++;
	}
	void append(const E&it)
	{
		assert(listSize < maxSize);
		listArry[listSize++] = it;
	}
	E remove()
	{
		assert((curr >= 0) && (curr < listSize));
		E it = listArry[curr];
		for (int i = curr; i < listSize - 1; i++)
			listArry[i] = listArry[i - 1];
		listSize--;
		return it;
	}
	void moveToStart(){	curr = 0;}
	void moveToEnd() { curr = listSize; }
	void prev() { if (curr != 0)curr--; }
	void next() { if (curr < listSize)curr++; }
	int length() const { return listSize; }
	int currPos() const { return curr; }
	void moveToPos(int pos)
	{
		assert((pos >= 0) && (pos < listSize));
		curr = pos;
	}
	const E& getValue () const
	{
		assert((curr >= 0) && (curr < listSize));
		return listArry[curr];
	}
};
//单链表类的实现:Single_List.h

template<typename E>
class SLink
{
public:
	E element;
	SLink*next;

	//两个构造函数
	SLink(const E&elemval, SLink*nextval = NULL)
	{
		element = elemval;
		next = nextval;
	}
	SLink(SLink*nextval = NULL) { next = nextval; }
};

template<typename E>
class SList :public List<E>
{
private:
	SLink<E>*head;
	SLink<E>*tail;
	SLink<E>*curr;//为了操作方便,这里的curr指向当前元素的上一个元素
	int cnt;//链表节点数

	//初始化函数
	void init()
	{
		curr = head = tail = new SLink<E>;
		cnt = 0;
	}

	void removeall()
	{
		while (head != NULL)
		{
			curr = head;
			head = head->next;
			delete curr;
		}
	}

public:
	SList(int size = 100) { init(); }//构造,默认大小100,没有什么实际用处,只是为了与前面保持一致
	~SList() { removeall(); }

	void print() const
	{
		SLink<E>*temp = head;
		for (int i = 0; i < cnt; i++)
		{
			temp = temp->next;
			cout <<temp->element<< " --> ";
		}
		cout << "NULL" << endl;
	}
	void clear() { removeall(); init(); }
	void insert(const E&it)
	{
		curr->next = new SLink<E>(it, curr->next);
		if (tail == curr)
			tail = curr->next;
		cnt++;
	}
	void append(const E&it)
	{
		tail = tail->next = new SLink<E>(it, NULL);
		cnt++;
	}
	E remove()
	{
		assert(curr->next != NULL);
		E it = curr->next->element;
		SLink<E>*ltemp = curr->next;
		if (tail = curr->next)
			tail = curr;
		curr->next = curr->next->next;
		delete ltemp;
		cnt--;
		return it;
	}
	void moveToStart() { curr = head; }
	void moveToEnd() { curr = tail; }
	void prev()
	{
		if (curr = head)
			return;
		SLink<E>*temp = head;
		while (temp->next != curr)
			temp = temp->next;
		curr = temp;
	}
	void next()
	{
		if (curr != tail)
			curr = curr->next;
	}
	int length() const{ return cnt; }
	int currPos()const
	{
		SLink<E>*temp = head;
		int i;
		for (i = 0; curr != temp; i++)
			temp = temp->next;
		return i;
	}
	void moveToPos(int pos)
	{
		assert(pos >= 0 && pos <= cnt);
		curr = head;
		for (int i = 0; i < pos; i++)
			curr = curr->next;
	}
	const E&getValue()const
	{
		assert(curr->next != NULL);
		return curr->next->element;
	}
};
//双链表类的实现:Double_List.h

template<typename E>
class DLink
{
public:
	E element;
	DLink*next;
	DLink*prev;

	DLink(const E&it, DLink*prevp, DLink*nextp)
	{
		element = it;
		prev = prevp;
		next = nextp;
	}
	DLink(DLink*prevp = NULL, DLink*nextp = NULL)
	{
		prev = prevp;
		next = nextp;
	}
};

template<typename E>
class DList :public DLink<E>
{
private:
	DLink<E>*head;
	DLink<E>*tail;
	DLink<E>*curr;
	int cnt;
	
	void init()
	{
		//这里的head&tail为表头表尾节点,均为NULL;
		curr = head = new DLink<E>;
		tail = new DLink<E>;
		head->next = tail;
		tail->prev = head;
		cnt = 0;
	}

	void removeall()
	{
		while (head != NULL)
		{
			curr = head;
			head = head->next;
			delete curr;
		}
	}

public:
	DList(int size = 100) { init(); }//构造,默认大小100,没有什么实际用处,只是为了与前面保持一致
	~DList() { removeall(); }

	void print() const
	{
		DLink<E>*temp = head;
		cout << "NULL <--> ";
		for (int i = 0; i < cnt; i++)
		{
			
			temp = temp->next;
			cout <<temp->element<< " <--> ";
		}
		cout << "NULL" << endl;
	}
	void clear() { removeall(); init(); }
	void insert(const E&it)
	{
		curr->next=curr->next->prev = new DLink<E>(it,curr, curr->next);
		cnt++;
	}
	void append(const E&it)
	{
		tail->prev = tail->prev->next = new DLink<E>(it, tail->prev,tail);
		cnt++;
	}
	E remove()
	{
		if (curr->next = tail)
			return NULL;
		E it = curr->next->element;
		DLink<E>*ltemp = curr->next;
		curr->next->next->prev=curr;
		curr->next = curr->next->next;
		delete ltemp;
		cnt--;
		return it;
	}
	void moveToStart() { curr = head; }
	void moveToEnd() { curr = tail; }
	void prev()
	{
		if(curr!=head)
			curr = curr->prev;
	}
	void next()
	{
		if (curr != tail)
			curr = curr->next;
	}
	int length() const { return cnt; }
	int currPos()const
	{
		DLink<E>*temp = head;
		int i;
		for (i = 0; curr != temp; i++)
			temp = temp->next;
		return i;
	}
	void moveToPos(int pos)
	{
		assert(pos >= 0 && pos <= cnt);
		curr = head;
		for (int i = 0; i < pos; i++)
			curr = curr->next;
	}
	const E&getValue()const
	{
		assert(curr->next != NULL);
		return curr->next->element;
	}
};
/*《数据结构与算法分析(第三版)》——线性表(p62-p76)*/

#include<iostream>
#include<cassert>
#include"ADT_List.h"
#include"AList.h"
#include"Single_List.h"
#include"Double_List.h"
using namespace std;

int main()
{
	
//test place

	system("pause");
}

基本概念与注意事项:

1.基本概念:空表、表头、表尾、有序线性表、无序线性表。

2.注意事项:

  • 在选择线性表的表示方法之前,首先应考虑这种表示法要支持的基本操作(表长度的增减、元素插入删除、获得元素的值、改变元素的值、表的生成清除和初始化、由当前节点找前驱后继元素等)。
  • 通过增加特殊的表头节点、表尾节点解决单双链表中的特例(链表为空或curr已经到达表头/表尾)。
  • 清除指针时,不要“丢失”被删除节点的内存,此内存应该返回给存储器;具体做法见代码中的析构函数。
  • 可利用空间表:取代较难使用的new和delete,更高效的使用内存,具体实现参见书本P70。
  • 双链表可以通过在一个指针域中存储两个指针值的异或结果来实现。

转载请注明出处:https://blog.csdn.net/Hodge_Z/article/details/85058673

猜你喜欢

转载自blog.csdn.net/Hodge_Z/article/details/85058673