C++实现单链表

一、单链表实现

单链表结构:数据域+指针域
单链表操作:1.创建单链表 2.遍历单链表 3.获取单链表的长度 4.判断单链表是否为空 5.获取节点 6.在尾部插入指定元素 7.在指定位置插入指定元素 8.在头部插入指定元素 9.在尾部删除元素 10.删除所有元素 11.删除指定元素 12.在头部删除元素 13.遍历反转链表 14.递归反转链表 0.退出
list.h

using DataType = int;

struct Node {
  DataType val;   // 数据域
  Node *next;     // 指针域
};

class LinkList {
 private:
  Node *head;
 public:
  LinkList();
  ~LinkList();
  void CreatLinkList(int n);
  void TraceLinkList();
  int GetLength();
  bool IsEmpty();
  Node* Find(DataType val);
  void InsertElemAtIndex(DataType val, int n);
  void InsertElemAtHead(DataType val);
  void InsertElemAtEnd(DataType val);
  void DeleteElemAtHead();
  void DeleteElemAtEnd();
  void DeleteAll();
  void DeleteElemVal(DataType val);
  void ReverseLinkList();
  Node* RecReverseLinkList(Node *head);
  void RecReverseLinkListFun();
};

list.cc

#include "./list.h"
#include <iostream>

// @description: 创建单链表
LinkList::LinkList() {
  head = new Node();
  head->val = 0;
  head->next = nullptr;
}

// @description: 销毁单链表
LinkList::~LinkList() {
  delete head;
}

// @description: 创建n个结点的单链表
void LinkList::CreatLinkList(int n) {
  Node *pnew, *ptemp;
  ptemp = head;
  if (n < 0) {
    std::cout << "input linklist size is error" << std::endl;
    return;
  }
  for (int i = 0; i < n; i++) {
    pnew = new Node();
    pnew->val = static_cast<DataType>(i);
    pnew->next = nullptr;
    ptemp->next = pnew;  // 增加新节点
    ptemp = pnew;        // 节点后移一位
  }
}

// @description: 遍历链表
void LinkList::TraceLinkList() {
  if (head == nullptr || head->next == nullptr) {
    std::cout << "linklist is null" << std::endl;
  }
  Node *temp = head;
  int index = 0;
  while (temp->next != nullptr) {
    temp = temp->next;
    std::cout << "linklist index is " << index++;
    std::cout << ", linklist val is " << temp->val << std::endl;
  }
}

// @description: 获取链表长度
int LinkList::GetLength() {
  int count = 0;
  Node *node = head->next;
  while(node != nullptr) {
    ++count;
    node = node->next;
  }
  return count;
}

// @description: 判断链表是否为空
bool LinkList::IsEmpty() {
  if (head->next == nullptr) {
    return true;
  }
  return false;
}

// @description: 查找指定数据的地址
Node *LinkList::Find(DataType data) {
  Node *node = head;
  if (node == nullptr) {
    std::cout << "find link list is nullptr" << std::endl;
    return nullptr;
  } else {
    while(node->next != nullptr) {
      if (node->val == data) {
        return node;
      }
      node = node->next;
    }
    return nullptr;
  }
}

// @description: 尾部插入指定数据
void LinkList::InsertElemAtEnd(DataType data) {
  Node *new_node = new Node();  // 新增的结点
  new_node->val = data;
  new_node->next = nullptr;
  Node *temp = head;
  if (head == nullptr) {
    head = new_node;
  } else {
    while (temp->next != nullptr) {
      temp = temp->next;
    }
    temp->next = new_node;  // 新增结点加入尾部
  }
}


// @description: 指定位置插入数据
void LinkList::InsertElemAtIndex(DataType data, int n) {
  if (n < 1 || GetLength() < n) {
    std::cout << "input value error" << std::endl;
  } else {
    Node *node = new Node();
    node->val = data;
    int count = 1;
    Node *temp = head;
    while (count < n) {  // 遍历n
      temp = temp->next;
      count++;
    }
    node->next = temp->next;
    temp->next = node;
  }
}

// @description: 头部插入指定数据
void LinkList::InsertElemAtHead(DataType data) {
  Node *new_node = new Node();
  new_node->val = data;
  Node *temp = head;   // 防止修改head指向
  if (head == nullptr) {
    head = new_node;
  }
  new_node->next = temp->next;
  temp->next = new_node;
}

// @description: 删除尾部元素
void LinkList::DeleteElemAtEnd() {
  Node *node = head;
  Node *temp = nullptr;
  if (node->next == nullptr) {
    std::cout << "link list is nullptr" << std::endl;
  } else {
    while (node->next != nullptr) {
      temp = node;
      node = node->next;
    }
    delete node;
    node = nullptr;
    temp->next = nullptr;
  }
}

// @description: 删除全部元素
void LinkList::DeleteAll() {
  Node *node = head->next;
  Node *temp = new Node();
  while (node != nullptr) {
    temp = node;
    node = node->next;
    head->next = node;
    temp->next = nullptr;
    delete temp;
  }
  head->next = nullptr;
}

// @description: 删除指定数据
void LinkList::DeleteElemVal(DataType data) {
  Node *temp = Find(data);
  if (temp == head->next) {
    DeleteElemAtHead();
  } else {
    Node *node = head;
    while(node->next != temp) {
      node = node->next;
    }
    node->next = temp->next;
    delete temp;
    temp = nullptr;
  }
}

// @description: 删除头部元素
void LinkList::DeleteElemAtHead() {
  Node *node = head;
  if (node == nullptr || node->next == nullptr) {
    std::cout << "link list is nullptr" << std::endl;
  } else {
    Node *temp = nullptr;
    node = node->next;
    temp = node->next;
    delete node;
    node = nullptr;
    head->next = temp;
  }
}

// @description: 遍历链表
void LinkList::ReverseLinkList() {
  // 1->2->3->4->5
  // 5->4->3->2->1
  // https://leetcode-cn.com/problems/reverse-linked-list/
  Node *node = head;
  if (node == nullptr || head->next == nullptr) {
    std::cout << "link list is nullptr" << std::endl;
    return;
  }
  node = node->next;
  Node *temp = nullptr;  // 临时保存的指针
  Node *new_list = temp;  // 保存已经反转之后的链表,最终需要返回的指针
  while (node != nullptr) {  // 循环遍历每一个变量
    temp = node;   // 指向当前需要反转的结点1
    node = node->next;   // 当前结点指向下一个结点2
    
    temp->next = new_list;   // 切断当前结点和后面结点之间的联系,指向已经反转之后的结点
    new_list = temp;   // 保存已经反转之后的指针
  }
  head->next = new_list;
}

// @description: 递归遍历链表
Node* LinkList::RecReverseLinkList(Node *head) {
  if (head == nullptr || head->next == nullptr) {
    return head;
  }
  Node *new_head = RecReverseLinkList(head->next);  // 递归
  head->next->next = head;  // 改变head->next的指向
  head->next = nullptr;  // head->next赋值为nullptr
  return new_head;
}

void LinkList::RecReverseLinkListFun() {
  head->next = RecReverseLinkList(head->next);
}

二、测试代码

test.cc

#include "./list.h"
#include <iostream>

void LinkListPrint() {
  std::cout << "1.创建单链表   2.遍历单链表   3.获取单链表的长度   4.判断单链表是否为空   5.获取节点\n";
  std::cout << "6.在尾部插入指定元素   7.在指定位置插入指定元素   8.在头部插入指定元素\n";
  std::cout << "9.在尾部删除元素   10.删除所有元素   11.删除指定元素   12.在头部删除元素\n";
  std::cout << "13.遍历反转链表   14.递归反转链表   0.退出" << std::endl;
}

void LinkListTest() {
  LinkList list;
  int index;
  do {
    (void)LinkListPrint();
    std::cout << "input index to execute" << std::endl;
    std::cin >> index;
    switch (index) {
    case 1:
      int length;
      std::cout << "input link list length" << std::endl;
      std::cin >> length;
      list.CreatLinkList(length);
      break;
    case 2:
      list.TraceLinkList();
      break;
    case 3:
      std::cout << "link list length is " << list.GetLength() << std::endl;
      break;
    case 4:
      if (list.IsEmpty() == true) {
        std::cout << "link list is empty" << std::endl;
      } else {
        std::cout << "link list is not empty" << std::endl;
      }
      break;
    case 5:
      DataType data;
      std::cout << "input data you want get" << std::endl;
      std::cin >> data;
      std::cout << "the data val is " << list.Find(data)->val << std::endl;
      break;
    case 6:
      DataType end_data;
      std::cout << "add data in the end of link list" << std::endl;
      std::cin >> end_data;
      list.InsertElemAtEnd(end_data);
      break;
    case 7:
      DataType index_data;
      int i;
      std::cout << "input data" << std::endl;
      std::cin >> index_data;
      std::cout << "input index" << std::endl;
      std::cin >> i;
      list.InsertElemAtIndex(index_data, i);
      break;
    case 8:
      DataType head_data;
      std::cout << "inset data at head" << std::endl;
      std::cin >> head_data;
      list.InsertElemAtHead(head_data);
      break;
    case 9:
      list.DeleteElemAtEnd();
      break;
    case 10:
      list.DeleteAll();
      break;
    case 11:
      DataType delete_data;
      std::cout << "input data you want to delete" << std::endl;
      std::cin >> delete_data;
      list.DeleteElemVal(delete_data);
      break;
    case 12:
      list.DeleteElemAtHead();
      break;
    case 13:
      list.ReverseLinkList();
      break;
    case 14:
      list.RecReverseLinkListFun();
    default:
      break;
    }
  } while (index != 0);
}

void TestReverseLinkList() {
  LinkList list;
  std::cout << "before reserse link list" << std::endl;
  list.CreatLinkList(10);
  list.TraceLinkList();
  std::cout << "after reserse link list" << std::endl;
  list.ReverseLinkList();
  list.TraceLinkList();
}

int main() {
  std::cout << "hello lch !!!" << std::endl;
  (void)LinkListTest();
  (void)TestReverseLinkList();
  std::cout << "end lch !!!" << std::endl;
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自动驾驶小哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值