static linked list(静态链表,结合数组实现)

一.之前已经写过单向链表和双向链表的指针实现,这是单向链表的数组实现,也称静态实现,即不需要通过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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值