链表实现

静态数组 - 带哨兵位单向非循环链表

const int N = 1e5 + 10; // 数据范围
int e[N], ne[N], h, id; // 数据域、指针域、哨兵结点、新分配单元位置

// 头插
void push_front(int data) {
    e[++id] = data;
    ne[id] = ne[h];
    ne[h] = id;
}

// 尾插
void push_back(int data) {
    int cur = 0;
    while (ne[cur])
        cur = ne[cur];
    e[++id] = data;
    ne[cur] = id;
}

// 中间插入
void insert_back(int data, int pos) {
    id++;
    e[id] = data;
    ne[id] = ne[pos];
    ne[pos] = id;
}

void erase_back(int pos) {
    if (ne[pos]) {
        // 判断不是最后一个元素
        // 若使用了mp数组,则此处还需要把mp数组内的标记清空:mp[e[ne[pos]]] = 0;

        // 让指向pos位置的指针域,改成原pos位置的下一个元素
        ne[pos] = ne[ne[pos]];
    }
}

// 按值查找,找不到则返回0
int find(int data) {
    for (int cur = ne[0]; cur; cur = ne[cur])
        if (e[cur] == data)
            return cur;
    return 0;
}

void print() {
    // 打印链表
    int cur = 0;
    for (cur = ne[h]; cur; cur = ne[cur])
        cout << e[cur] << " ";
    cout << endl;
}

静态链表(含mp[]版本)

const int N = 1e5 + 10;
int e[N], pre[N], ne[N], h, id;
int mp[N]; // mp[i]表示i的位置

void push_front(int data) {
    e[++id] = data;
    pre[id] = h; // 新来结点的左指针
    ne[id] = ne[h]; // 新来结点的右指针

    mp[data] = id;

    pre[ne[h]] = id; // 修改原来第一个结点的左指针
    ne[h] = id; // 修改头结点的右指针
}

int find(int data) {
    // 按值查找,使用mp优化
    return mp[data];
}

void insert_back(int data, int pos) {
    e[++id] = data;
    ne[id] = ne[pos];
    pre[id] = pos;

    mp[data] = id;

    ne[pos] = id; // 修改pos位置的后继
    pre[ne[id]] = id; // 修改ne[id]的前驱
}

void insert_front(int data, int pos) {
    e[++id] = data;
    ne[id] = pos;
    pre[id] = pre[pos];

    mp[data] = id;

    ne[pre[pos]] = id; // 修改pre[pos]位置的后继
    pre[pos] = id; // 修改pos位置的前驱
}

void erase(int pos) {
    mp[e[pos]] = 0;

    ne[pre[pos]] = ne[pos]; // 修改pre[pos]的后继
    pre[ne[pos]] = pre[pos]; // 修改ne[pos]的前驱
}

静态数组 - 不带哨兵位单向非循环链表

#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int e[2 * N], ne[2 * N], id, h[N];

// 头插
void push_front(const int& list, const int& data) {
    e[++id] = data;
    ne[id] = h[list];
    h[list] = id;
}

// 遍历
void print(const int& list) {
    int cur = 0;
    for (int cur = h[list]; cur; cur = cur = ne[cur])
        cout << e[cur] << " ";
    cout << endl;
}

// 树、图中,常常这样加入一条边
void addEdge(const int& a, const int& b) {
    e[++id] = b;
    ne[id] = h[a];
    h[a] = id;

    e[++id] = a;
    ne[id] = h[b];
    h[b] = id;
}

int main() {
    push_front(1, 1);
    push_front(1, 2);
    print(1);
    print(2);
    return 0;
}

动态扩容无头单向非循环链表

  • 定义链表数据结构

    • 数据类型定义

      typedef int data_type; // 定义元素的数据类型
      typedef struct {
          data_type data;
          struct node* next;
      } node;
      
      typedef struct {
          node* phead;
      } list;

      说明:

      • 节点类型:含数据、下一个节点的指针
      • 链表类型:含第一个节点指针,并用于维护链表
    • 节点的创建

      static node* new_node(data_type data) {
          // 生成一个新结点
          node* newnode = (node*)malloc(sizeof(node));
          if (newnode == NULL)
              exit(0);
          else {
              newnode->next = NULL;
              newnode->data = data;
          }
          return newnode;
      }

      注:

      • 使用了static关键字,表示只在链表实现中使用
      • 销毁节点的代码不写,因为只由销毁链表删除所有节点(以及删除元素时释放节点内存)
    • 初始化函数

      list* init() {
          list* ret = (list*)malloc(sizeof(list));
          ret->phead = NULL;
          return ret;
      }
    • 销毁函数

      void destory(list* ptr) {
          assert(ptr && ptr->phead);
      
          // 从头节点出发,依次释放所有节点内存
          node* cur = ptr->phead;
          if (cur) {
              node* next = cur->next;
              while (cur != NULL) {
                  free(cur);
                  cur = next;
                  if (cur)
                      next = cur->next;
              }
          }
          free(ptr);
      }
  • 接口实现

    • insert_front()

      void insert_front(list* ptr, node* pos, data_type data) {
          assert(ptr);
      
          if (ptr->phead == NULL || ptr->phead == pos) {
              // 为第一个结点的情况
              node* newnode = new_node(data);
      
              newnode->next = ptr->phead;
              ptr->phead = newnode;
          }
          else {
              node* prev = ptr->phead;
              while (prev->next != pos)
                  prev = prev->next;
      
              node* newnode = new_node(data);
              newnode->next = prev->next;
              prev->next = newnode;
          }
      }
    • erase()

      void erase(list* ptr, node* pos) {
          assert(ptr && ptr->phead && pos);
      
          if (pos == ptr->phead) {
              // 为第一个结点的情况
              node* newhead = ptr->phead->next;
              free(ptr->phead);
              ptr->phead = newhead;
          }
          else {
              node* prev = ptr->phead;
              while (prev->next != pos)
                  prev = prev->next;
      
              prev->next = pos->next;
              free(pos);
          }
      }
    • 头插、头删

      void push_front(list* ptr, data_type data) {
          insert_front(ptr, ptr->phead, data);
      }
      
      void pop_front(list* ptr) {
          erase(ptr, ptr->phead);
      }
    • 其他接口

      int size(list* ptr) {
          assert(ptr);
      
          int ret = 0;
          node* cur = ptr->phead;
          while (cur) {
              cur = cur->next;
              ret++;
          }
          return ret;
      }
      
      node* find(list* ptr, data_type data) {
          // 按值查找,返回地址,未找到则返回空指针
          assert(ptr);
      
          node* cur = NULL;
          for (cur = ptr->phead; cur; cur = cur->next) {
              if (cur->data == data)
                  return cur;
          }
          return NULL;
      }
      
      data_type at(list* ptr, int loc) {
          // 按位查找
          assert(ptr);
      
          int i = 0;
          node* cur = ptr->phead;
          for (i = 0; i < loc; i++) {
              assert(cur);
              cur = cur->next;
          }
          return cur->data;
      }

动态扩容有头双向循环链表

  • 定义链表数据结构

    • 数据类型定义

      typedef int data_type;
      typedef struct node {
          struct node* prev; // 上一个结点指针
          data_type data; // 数据
          struct node* next; // 下一个结点指针
      } node;
    • 生成新结点

      static node* new_node(data_type data) {
          // 生成新结点
          node* newnode = (node*)malloc(sizeof(node));
          if (newnode == NULL)
              exit(0);
      
          newnode->data = data;
          newnode->prev = NULL;
          newnode->next = NULL;
      
          return newnode;
      }
    • 链表的初始化

      node* init() {
          // 链表的初始化,返回哨兵位的头结点
          node* newnode = new_node(0);
          newnode->next = newnode;
          newnode->prev = newnode;
          return newnode;
      }
    • 销毁函数

      void destory(node* plist) {
          assert(plist);
      
          node* cur = plist->next;
          node* next = cur->next;
          while (cur != plist) {
              free(cur);
              cur = next;
              next = cur->next;
          }
          free(plist);
      }
  • 接口实现

    • insert_front()、erase()

      void insert_front(node* pos, data_type data) {
          assert(pos);
      
          node* newnode = new_node(data);
      
          node* prev = pos->prev;
          prev->next = newnode;
          newnode->prev = prev;
          newnode->next = pos;
          pos->prev = newnode;
      }
      
      void erase(node* pos) {
          assert(pos);
      
          // 链接新的链表顺序
          (pos->prev)->next = pos->next;
          (pos->next)->prev = pos->prev;
      
          // 释放空间
          free(pos);
          pos = NULL;
      }
    • 尾插、头插、尾删、头删

      void push_back(node* plist, data_type data) {
          insert_front(plist, data);
      }
      
      void push_front(node* plist, data_type data) {
          insert_front(plist->next, data);
      }
      
      void pop_back(node* plist) {
          assert(plist);
      
          if (plist->prev != plist)
              erase(plist->prev);
      }
      
      void pop_front(node* plist) {
          assert(plist);
      
          if (plist->next != plist)
              erase(plist->next);
      }
    • 其他接口

      node* find(node* plist, data_type data) {
          // 按值查找,未找到则返回空指针
          assert(plist);
      
          node* cur = NULL;
          for (cur = plist->next; cur != plist; cur = cur->next) {
              if (cur->data == data)
                  return cur;
          }
          return NULL;
      }
« 顺序表实现 ← 返回列表 栈实现 »