10单向链表(slist)

本文介绍了C++ STL中slist的相关知识。slist迭代器是单向的,与list迭代器不同,除起点外其他位置的insert和erase操作不便,因此提供insert_after和erase_after。其节点和迭代器设计架构复杂,初始化的slist有一个head节点,还介绍了push_front等元素操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、slist概述

slist并不在标准规格之内,sllist和list的主要差别在于,slist的迭代器属于单向的Forward Iterator,而list的迭代器属于双向的Bidirectional Iterator。由于slist没有任何方便的办法可以回头定出前一个位置,必须从头找起,所以对于slist除了起点外其他位置采用insert和erase操作都属于不智之举,这是slist相较于list的大缺点。为此,slist特别提供了insert_after()和erase_after()供灵活运用。同样slist不提供push_back()只提供push_front(),因此slist的元素次序会和元素插入进来的次序相反。

2、slist的节点

slist节点和其迭代器的设计,架构上比list复杂许多,运用了继承关系,因此在性别转换上有复杂的表现。__slist_node继承自__slist_node_base,__slist_iterator继承自__slist_iterator_base。

struct __slist_node_base
{
  __slist_node_base* next;
};
template <class T>
struct __slist_node : public __slist_node_base
{
  T data;
};

2、slist迭代器

struct __slist_iterator_base
{
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  typedef forward_iterator_tag iterator_category;

  __slist_node_base* node;

  __slist_iterator_base(__slist_node_base* x) : node(x) {}
  void incr() { node = node->next; }

  bool operator==(const __slist_iterator_base& x) const {
    return node == x.node;
  }
  bool operator!=(const __slist_iterator_base& x) const {
    return node != x.node;
  }
};

template <class T, class Ref, class Ptr>
struct __slist_iterator : public __slist_iterator_base
{
  typedef __slist_iterator<T, T&, T*>             iterator;
  typedef __slist_iterator<T, const T&, const T*> const_iterator;
  typedef __slist_iterator<T, Ref, Ptr>           self;

  typedef T value_type;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef __slist_node<T> list_node;

  __slist_iterator(list_node* x) : __slist_iterator_base(x) {}
  __slist_iterator() : __slist_iterator_base(0) {}
  __slist_iterator(const iterator& x) : __slist_iterator_base(x.node) {}

  reference operator*() const { return ((list_node*) node)->data; }
  pointer operator->() const { return &(operator*()); }

  self& operator++()
  {
    incr();
    return *this;
  }
  self operator++(int)
  {
    self tmp = *this;
    incr();
    return tmp;
  }
};

3、slist数据结构

初始化的slist就一个head节点对象,head没有data数据成员只有一个next成员,head.next=0。

template <class T, class Alloc = alloc>
class slist
{
public:
  typedef T value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;

  typedef __slist_iterator<T, T&, T*>             iterator;
  typedef __slist_iterator<T, const T&, const T*> const_iterator;

private:
  typedef __slist_node<T> list_node;
  typedef __slist_node_base list_node_base;
  typedef __slist_iterator_base iterator_base;
  typedef simple_alloc<list_node, Alloc> list_node_allocator;

  static list_node* create_node(const value_type& x) {
    list_node* node = list_node_allocator::allocate();
    __STL_TRY {
      construct(&node->data, x);
      node->next = 0;
    }
    __STL_UNWIND(list_node_allocator::deallocate(node));
    return node;
  }

  static void destroy_node(list_node* node) {
    destroy(&node->data);
    list_node_allocator::deallocate(node);
  }

private:
  list_node_base head;

public:
  slist() { head.next = 0; }
  slist(size_type n, const value_type& x) { fill_initialize(n, x); }
  slist(int n, const value_type& x) { fill_initialize(n, x); }
  slist(long n, const value_type& x) { fill_initialize(n, x); }
  explicit slist(size_type n) { fill_initialize(n, value_type()); }
  template <class InputIterator>
  slist(InputIterator first, InputIterator last) {
    range_initialize(first, last);
  }
  slist(const_iterator first, const_iterator last) {
    range_initialize(first, last);
  }
  slist(const value_type* first, const value_type* last) {
    range_initialize(first, last);
  }
  slist(const slist& L) { range_initialize(L.begin(), L.end()); }
  slist& operator= (const slist& L);
  ~slist() { clear(); }

public:
  iterator begin() { return iterator((list_node*)head.next); }
  const_iterator begin() const { return const_iterator((list_node*)head.next);}
  iterator end() { return iterator(0); }
  const_iterator end() const { return const_iterator(0); }
  size_type size() const { return __slist_size(head.next); }
  size_type max_size() const { return size_type(-1); }
  bool empty() const { return head.next == 0; }
  void swap(slist& L)
  {
    list_node_base* tmp = head.next;
    head.next = L.head.next;
    L.head.next = tmp;
  }

public:
  reference front() { return ((list_node*) head.next)->data; }
  const_reference front() const { return ((list_node*) head.next)->data; }
  void push_front(const value_type& x)   {
    __slist_make_link(&head, create_node(x));
  }
  void pop_front() {
    list_node* node = (list_node*) head.next;
    head.next = node->next;
    destroy_node(node);
  }
}

4、slist元素操作

(1)push_front

inline __slist_node_base* __slist_make_link(__slist_node_base* prev_node,
                                            __slist_node_base* new_node)
{
  new_node->next = prev_node->next;
  prev_node->next = new_node;
  return new_node;
}
void push_front(const value_type& x)   {
    __slist_make_link(&head, create_node(x));
}

(2)pop_front

void pop_front() {
    list_node* node = (list_node*) head.next;
    head.next = node->next;
    destroy_node(node);
}

(3)erase_after

list_node_base* erase_after(list_node_base* pos) {
    list_node* next = (list_node*) (pos->next);
    list_node_base* next_next = next->next;
    pos->next = next_next;
    destroy_node(next);
    return next_next;
}

(4)insert_after

iterator insert_after(iterator pos, const value_type& x) {
    return iterator(_insert_after(pos.node, x));
}
list_node* _insert_after(list_node_base* pos, const value_type& x) {
    return (list_node*) (__slist_make_link(pos, create_node(x)));
}
inline __slist_node_base* __slist_make_link(__slist_node_base* prev_node,
                                            __slist_node_base* new_node)
{
  new_node->next = prev_node->next;
  prev_node->next = new_node;
  return new_node;
}

 

好的,我可以为你编写这个函数。下面是代码示例: ``` #include <stdio.h> #include <stdlib.h> typedef struct SLIST{ int data; struct SLIST *next; }SLIST_S; int list_revert(SLIST_S *listA, SLIST_S **listB) { if (listA == NULL) { return -1; } SLIST_S *prev = NULL; SLIST_S *cur = listA; SLIST_S *next = NULL; while (cur != NULL) { next = cur->next; cur->next = prev; prev = cur; cur = next; } *listB = prev; return 0; } int main() { // 创建单向链表 SLIST_S *head = (SLIST_S *)malloc(sizeof(SLIST_S)); SLIST_S *node1 = (SLIST_S *)malloc(sizeof(SLIST_S)); SLIST_S *node2 = (SLIST_S *)malloc(sizeof(SLIST_S)); SLIST_S *node3 = (SLIST_S *)malloc(sizeof(SLIST_S)); head->data = 1; node1->data = 2; node2->data = 3; node3->data = 4; head->next = node1; node1->next = node2; node2->next = node3; node3->next = NULL; // 打印反转前的单向链表 SLIST_S *p = head; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); // 反转单向链表 SLIST_S *new_head = NULL; list_revert(head, &new_head); // 打印反转后的单向链表 p = new_head; while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); return 0; } ``` 函数`list_revert(SLIST_S *listA, SLIST_S **listB)`接受两个参数,第一个参数是要反转的单向链表的头指针`listA`,第二个参数是返回的反转后的单向链表的头指针`listB`的地址。 在函数中,我们使用了三个指针变量`prev`、`cur`和`next`,其中`prev`指向当前节点的前一个节点,`cur`指向当前节点,`next`指向当前节点的后一个节点。我们从头节点开始遍历单向链表,每次将`cur`节点的`next`指针指向`prev`节点,然后将`prev`和`cur`同时向后移动一个节点,直到遍历完整个单向链表,最后将`listB`指向反转后的单向链表的头节点`prev`。 在`main`函数中,我们创建了一个单向链表,然后调用`list_revert`函数将其反转,并打印反转前后的单向链表,以便验证反转是否成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值