内容概要:
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