一.之前已经写过单向链表和双向链表的指针实现,这是单向链表的数组实现,也称静态实现,即不需要通过new和delete动态管理内存
总体与指针的实现相似,利用元素所在数组中的位置作为指针next的依据
// 用节点数组实现链表的各种操作
// 与指针实现类似
#include "list.hpp"
#include <string>
#include <sstream>
#include <assert.h>
list::list() { this->clear(); }
// 注意在clear中同时对各个成员变量进行了初始化
// 特别是next的初始化
list::list(const list& another) { *(this) = another; }
list::~list() {}
list& list::operator=(const list& another) {
// 直接赋值即可
// 不需要new内存等问题
this->clear();
for (int i = 0; i < MAX_STORAGE; i++) {
storage[i] = another.storage[i];
}
this->head = another.head;
this->empty_head = another.empty_head;
this->_size = another._size;
return *(this);
}
bool list::empty(void) const { return this->_size == 0; }
list::size_type list::size(void) const { return this->_size; }
std::string list::toString(void) const {
pointer p = this->head;
std::string ret;
while (p != nullpointer) {
// 将stringstream ss放在while之外,然后使用ss.clear() 无法实现清空的作用
// 所以用这种方法是最好的
std::stringstream ss;
ss << this->storage[p].data;
ret += ss.str();
ret += "->";
p = this->storage[p].next;
}
ret += "NULL";
return ret;
}
void list::insert(int position, const int& data) {
// 与指针的实现原理是一样的
// 首先判断是否能够插入
// 第一个需要满足的情况是position的范围.
// 第二个需要满足的情况是 _size不能超过数组最大值
if (position >= 0 && position <= this->_size) {
if (this->_size + 1 <= MAX_STORAGE) {
// empty_head表示的是数组中没有存入数据的内存所在的数组index
// 从clear中可知,empty_head实现了数组往下一个一个移动的作用
pointer freeNode = empty_head;
empty_head = storage[empty_head].next;
storage[freeNode].data = data;
// position == 0的情况通常需要特殊考虑是因为涉及到head的值的改变
if (position == 0) {
storage[freeNode].next = head;
head = freeNode;
} else {
pointer p = head;
for (int i = 0; i < position - 1; i++) {
p = storage[p].next;
}
storage[freeNode].next = storage[p].next;
storage[p].next = freeNode;
}
this->_size++;
}
}
}
void list::erase(int position) {
// 判断是否能够进行删除操作
if (position >= 0 && position < this->_size) {
if (position == 0) {
pointer temp = head;
head = storage[head].next;
storage[temp].next = empty_head;
empty_head = temp;
} else {
pointer p = head;
for (int i = 0; i < position - 1; i++) {
p = storage[p].next;
}
pointer temp = storage[p].next;
assert(storage[p].next != nullpointer);
// assert函数 如果为假.通过调用obsort终止程序运行
// 传进去的参数是一个表达式比如, i < 100或者是 p != NULL等等
storage[p].next = storage[storage[p].next].next;
storage[temp].next = empty_head;
empty_head = temp;
}
this->_size--;
}
}
void list::clear(void) {
this->head = nullpointer;
this->_size = 0;
this->empty_head = 0;
// 对next的操作
for (int i = 0; i < MAX_STORAGE - 1; i++) {
storage[i].next = i + 1;
}
// 最后一个数组元素的下一个指向空
storage[MAX_STORAGE - 1].next = nullpointer;
}
list& list::sort(void) {
// 与指针链表的排序相同
// 首先如果前一个元素比后一个元素要小,则指针分别往下移动
// 如果前一个元素比后一个元素大,则首先判断fast上的元素是否比head节点中的值小,如果是的话,head中的值需要进行改变
// 此处单独考虑
// 如果不是的话,对当前的fast中的值与从head到fast之间的节点一个一个进行比较,并将fast插入到正确的位置
// 重点是 slow->next = fast->next;
// fast->next = pre->next;
// pre->next = fast;
// 注意最后要重新让fast = slow->next;
// 以便继续进行比较和排序
if (this->head != nullpointer && this->storage[head].next != nullpointer) {
pointer slow = head;
pointer fast = storage[head].next;
while (fast != nullpointer) {
if (storage[fast].data >= storage[slow].data) {
fast = storage[fast].next;
slow = storage[slow].next;
} else {
pointer pre = this->head;
if (storage[head].data > storage[fast].data) {
storage[slow].next = storage[fast].next;
storage[fast].next = this->head;
this->head = fast;
} else {
while (storage[storage[pre].next].data <= storage[fast].data) {
pre = storage[pre].next;
}
storage[slow].next = storage[fast].next;
storage[fast].next = storage[pre].next;
storage[pre].next = fast;
}
fast = storage[slow].next;
}
}
}
return *(this);
}
注: 一些需要注意的地方已经在代码中直接用注释的方式注明,重点需要理解的是insert, erase, sort和clear四个函数的实现过程,可以通过实例一步步理解,思路会清晰的多,再有是链表问题尽量画图进行理解
重点:insert函数的理解:insert函数传进去的是一个表达式,对表达式进行判断,如果表达式不正确,则会通过调用obsort函数终止程序的运行
下面是:list.hpp
#ifndef LIST_H_
#define LIST_H_
#include <string>
#define MAX_STORAGE 1000
class list{
typedef int data_type;
typedef int pointer;
typedef unsigned int size_type;
static const pointer nullpointer = -1;
typedef struct node {
data_type data;
pointer next;
node(const node &another) {
this->operator=(another);
}
node& operator=(const node &another) {
this->data = another.data;
this->next = another.next;
}
node(data_type data = 0, pointer next = nullpointer) : data(data), next(next) {}
} node;
node storage[MAX_STORAGE];
size_type _size;
pointer head;
pointer empty_head;
public:
list();
list(const list& another);
list& operator=(const list&);
~list();
// Capacity
bool empty(void) const;
size_type size(void) const;
// output
// list: [1,2,3,4,5]
// output: 1->2->3->4->5->NULL
std::string toString(void) const;
void insert(int position, const int& data);
void erase(int position);
void clear(void);
list& sort(void);
};
#endif // !LIST_H_
下面是main.cpp测试部分
#include <string>
#include "list.hpp"
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
list li;
int n;
cin >> n;
for (int i = 0, data, pos; i < n; i++) {
cin >> pos >> data;
li.insert(pos, data);
}
cout << li.toString() << " size: " << li.size() << endl;
list li2(li);
list li3;
li = li3 = li2 = li;
cout << li.toString() << " size: " << li.size() << endl;
cout << li2.toString() << " size: " << li2.size() << endl;
cout << li3.toString() << " size: " << li3.size() << endl;
int m;
cin >> m;
for (int i = 0, pos; i < m; i++) {
cin >> pos;
li.erase(pos);
}
for (int i = 0, temp; i < m; i++) {
cin >> temp;
li.insert(0, temp);
}
cout << li.toString() << endl;
cout << li.sort().toString() << endl;
cout << li2.sort().toString() << endl;
cout << li3.sort().toString() << endl;
return 0;
}
下面是测试样例:
5
0 2
1 3
2 5
3 6
2 4
2->3->4->5->6->NULL size: 5
2->3->4->5->6->NULL size: 5
2->3->4->5->6->NULL size: 5
2->3->4->5->6->NULL size: 5
1
1
1
1->2->4->5->6->NULL
1->2->4->5->6->NULL
2->3->4->5->6->NULL
2->3->4->5->6->NULL