天天看點

C++實作順序表與連結清單

C++實作順序表與連結清單

一、順序表

之前已經對順序表有了了解,需要注意的是讀者如果疑惑以下代碼沒有實作頭插與頭删,是因為代碼中任意插入與删除這兩個函數可以實作此功能。下面有測試代碼,讀者也可以自行測試

代碼如下:

#include<iostream>
using namespace std;
#include<assert.h>
typedef int DataType;
class SeqList
{
public:
  //構造函數
  SeqList()
    : _array(new DataType[3])
    , _capacity(3)
    , _size(0)
  {}

  //帶參數的構造函數
  SeqList(DataType *array, size_t size)
    : _array(new DataType[size])
    , _capacity(size)
    , _size(size)
  {
    for (size_t i = 0; i < size; ++i)
      _array[i] = array[i];
  }

  //拷貝構造函數
  SeqList(const SeqList& s)
    :_array(new DataType[s._capacity])
    , _capacity(s._capacity)
    , _size(s._size)
  {
    for (size_t i = 0; i < s._size; ++i)
      _array[i] = s._array[i];
  }

  //運算符=重載
  SeqList& operator=(const SeqList& s)
  {
    DataType *tmp = new DataType[s._capacity];
    memcpy(tmp, s._array, s._size);
    delete[] _array;
    _array = tmp;
    _capacity = s._capacity;
    _size = s._size;
  }

  ~SeqList()
  {
    if (_array)
    {
      delete[] _array;
      _size = 0;
      _capacity = 0;
    }
  }

  void PushBack(int data)
  {
    _CheckCapacity();
    _array[_size] = data;
    _size++;
  }
  void PopBack()
  {
    _size--;
  }
  void Insert(size_t pos, DataType data)
  {
    _CheckCapacity();
    size_t end = _size;
    while (end >= pos)
    {
      _array[end] = _array[end - 1];
      end--;
    }
    _array[pos - 1] = data;
    _size++;
  }
  void Erase(size_t pos)
  {
    assert(pos < _size);
    size_t tmp = pos;
    while (tmp < _size)
    {
      _array[tmp-1] = _array[tmp];
      tmp++;
    }
    _array[tmp] = _array[_size-1];
    _size--;
  }
  size_t Size()const
  {
    return _size;
  }
  size_t Capacity()const
  {
    return _capacity;
  }
  bool Empty()const
  {
    return _size == 0;
  }
  DataType& operator[](size_t index)
  {
    return _array[index];
  }
  const DataType& operator[](size_t index)const
  {
    return _array[index];
  }

  // 傳回順序表中的第一個元素 
  DataType& Front()
  {
    return _array[0];
  }
  const DataType& Front()const
  {
    return _array[0];
  }
  // 傳回順序表中最後一個元素 
  DataType& Back()
  {
    return _array[_size-1];
  }
  const DataType& Back()const
  {
    return _array[_size - 1];
  }

  // 清空順序表中的所有元素 
  void Clear()
  {
    _size = 0;
  }

  // reserve() 
  // 将順序表中元素個數改變到newSize 
  void ReSize(size_t newSize, const DataType& data = DataType())
  {
    if (newSize <= _size)
    {
      _size = newSize;
    }
    else if ((newSize > _size)&&(newSize <= _capacity))
    {
      for (size_t i = _size; i < newSize; i++)
      {
        _array[i] = data;
      }
      _size = newSize;
    }
    else
    {
      DataType *tmp = new DataType[newSize];
      for (size_t i = 0; i < _size; i++)
      {
        tmp[i] = _array[i];
      }
      for (size_t j = _size; j < newSize; j++)
      {
        tmp[j] = data;
      }
      delete[] _array;
      _array = tmp;
      _size = newSize;
      _capacity = newSize;
    }
  }
  friend ostream& operator<<(ostream& _cout, const SeqList& s)
  {
    for (size_t i = 0; i < s._size; i++)
    {
      cout << s._array[i] << " ";
    }
    cout << endl;
    return cout;
  }
private:
  void _CheckCapacity()
  {
    if (_size == _capacity)
    {
      _capacity = _capacity * 2 + 3;
      DataType *tmp = new DataType[_capacity];
      for (size_t i = 0; i < _size; i++)
      {
        tmp[i] = _array[i];
      }
      delete _array;
      _array = tmp;
    }
  }
private:
  DataType *_array;
  size_t _size;
  size_t _capacity;
};
void test()
{
  SeqList s;
  s.PushBack(1);
  s.PushBack(2);
  s.PushBack(3);
  s.PushBack(4);
  cout << s;
  cout << s.Size() << endl;

  s.Insert(1, 0);            //頭插0
  s.Erase(3);                //删除第三個數
  cout << s;

  s.PopBack();             
  s.ReSize(10);             //改變大小

  cout << s.Empty() << endl;
  cout << s.Back() << endl;
  cout << s.Front() << endl;

  cout << s.Size() << endl;
  cout << s.Capacity() << endl;
}
int main()
{
  test();
  system("pause");
  return 0;
}      

測試結果:

C++實作順序表與連結清單

二、雙向連結清單

代碼如下:

#include<iostream>
#include<assert.h>
using namespace std;
typedef int DataType;
struct Node
{
  Node()
      : _pNext(NULL)
      , _pPre(NULL)
      , _data(NULL)
  {}

  Node(const DataType& data)
  : _pNext(NULL)
  , _pPre(NULL)
  , _data(data)
  {}

  Node* _pNext;
  Node* _pPre;
  DataType _data;
};

class List
{
public:
  List()
  {
    _pHead = new Node;
  }

  List(DataType* array, size_t size)
  {
    for (size_t i = 0; i < size; ++i)
      PushBack(array[i]);
  } 
  void PushBack(const DataType data)
  {
    Node* pTail = _pHead;
    while (pTail->_pNext != NULL)
    {
      pTail = pTail->_pNext;
    }
    Node* pNewNode = new Node(data);
    pTail->_pNext = pNewNode;
    pNewNode->_pPre = pTail;
  }

  void PopBack()
  {
    assert(this);
    if (_pHead->_pNext == NULL)  //空鍊
    {
      cout << "空鍊" << endl;
      return;
    }
    Node *tmp = _pHead;
    while ((tmp != NULL)&&(tmp->_pNext != NULL))
    {
      tmp = tmp->_pNext;
    }
    Node *node = tmp->_pPre;
    delete tmp;
    node->_pNext = NULL;
  }

  void PushFront(const DataType data)
  {
    assert(this);
    if (_pHead->_pNext == NULL)
    {
      PushBack(data);
    }
    else
    {
      Node *node = new Node(data);
      Node *Cur = _pHead->_pNext;
      _pHead->_pNext = node;
      node->_pPre = _pHead;
      node->_pNext = Cur;
      Cur->_pPre = node;
    }
  }

  void PopFront()
  {
    assert(this);
    if (_pHead->_pNext == NULL)
    {
      cout << "空鍊" << endl;
      return;
    }
    Node *node = _pHead->_pNext->_pNext;
    delete (_pHead->_pNext);
    if (node == NULL)           //隻有一個節點
    {
      _pHead->_pNext = NULL;
      return;
    }
    node->_pPre = _pHead;
    _pHead->_pNext = node;
  }

  void Erase(Node* pos)
  {
    assert(this);
    Node *cur = pos->_pPre;
    Node *next = pos->_pNext;
    cur->_pNext = next;
    next->_pPre= cur;
    delete pos;
    pos = NULL;
  }

  Node *Find(const DataType d)   //查詢節點位置
  {
    assert(this);
    Node *tmp = _pHead;
    while (tmp != NULL)
    {
      if (tmp->_data == d)
      {
        return tmp;
      }
      tmp = tmp->_pNext;
    }
  }

  void Insert(Node* pos, const DataType& data)   //指定位置插入
  {
    assert(this);
    Node *cur = pos->_pNext;
    Node *tmp = new Node(data);
    pos->_pNext = tmp;
    tmp->_pPre = pos;
    tmp->_pNext = cur;
    cur->_pPre = tmp;
  }

  size_t Size()              //連結清單元素個數
  {
    int count = 0;
    Node *cur = _pHead->_pNext;
    while (cur != NULL)
    {
      cur = cur->_pNext;
      count++;
    }
    return count;
  }   

  void Clear()                //清空
  {
    assert(this);
    if (_pHead == NULL)
    {
      cout << "空鍊" << endl;
      return;
    }
    Node *tmp = _pHead->_pNext;
    Node *next = tmp->_pNext;
    while (tmp->_pNext!= NULL)
    {
      delete tmp;
      tmp = next;
      next = next->_pNext;
    }
    _pHead->_pNext = NULL;
  }    

  void display()
  {
    assert(this);
    Node *cur = _pHead->_pNext;
    if (cur == NULL)
    {
      cout << "空鍊" << endl;
      return;
    }
    while (cur != NULL)
    {
      cout << cur->_data << " ";
      cur = cur->_pNext;
    }
    cout << endl;
  }
private:
  Node* _pHead;
};
int main()
{
  List l1;
  l1.PushFront(4);
  l1.PushFront(3);
  l1.PushFront(2);
  l1.PushFront(1);

  l1.PushBack(5);
  l1.PushBack(6);
  l1.display();

  l1.PopBack();
  l1.PopFront();
  l1.display();
  cout << l1.Size() << endl;

  l1.Erase(l1.Find(4));
  l1.display();
  l1.Insert(l1.Find(2), 3);
  l1.display();

  l1.Clear();
  cout << l1.Size() << endl;

  system("pause");
  return 0;
}      

運作結果如下:

C++實作順序表與連結清單