新手上路,勿喷。C++链表的创建,遍历,删除,插入等等

//list.h

#pragma once
template<typename T>class slistNode
{
public:
 slistNode() { next = nullptr; cout << "调用了slistnode的构造函数" << endl; }
 ~slistNode() {delete next;cout << "调用了slistnode的析构函数" << endl;};
 T data;
 slistNode* next;
};

template<typename T>
class myslist
{
 private:
  unsigned int listlength; 
  slistNode<T>* headnode; 
 public:
  myslist();//初始化  
  ~myslist();//用于删除lastnode,headnode。他们动态分配了内存
  unsigned int length();//链表元素的个数      
  bool add(int n);//在链表的头部插入节点     
  void traversal();//遍历整个链表并打印      
  bool isEmpty();//判断链表是否为空      
  slistNode<T>* find(T x);//查找第一个值为x的节点,返回节点的地址,找不到返回NULL      
  void Delete(T x);//删除第一个值为x的节点      
  bool insert(T x,int n);//在第n个节点后插入值为x的节点       
  bool insertlast(T x);//在链表的尾部插入节点
};
template<typename T>
myslist<T>::~myslist()
{
 delete headnode;
 cout << "调用的myslist的析构函数" << endl;
}

template<typename T>
myslist<T>::myslist()
{
 cout << "调用的myslist的构造函数" << endl;
 headnode = new slistNode<T>();//这里调用默认构造函数,所以head->next=nullptr;如果有形参,则调用对应的构造函数。
 headnode->data = 0;
 listlength = 0;
}

template<typename T>
unsigned int myslist<T>::length()
{
 return listlength;
}

template<typename T>
bool myslist<T>::add(int n)
{
 int i = 0;
 for (i; i < n; i++)
 {
  cout << "请输入你想插入的第" <<n-i << "个数据";
  T data1;
  cin >> data1;
  cout << endl;
  //下面这个动态指针分配了地址的,这样每次后生成的位置都会指向在它之前生成的那个节点的指针域。
  slistNode<T>* node = new slistNode<T>();
  if (node == nullptr)
  {
   cout << "动态内存分配失败" << endl;
   return 0;
  }
  //每次头节点指向的位置都是上一次循环生成的节点的地址,这使得每个节点都是在头节点后面插入的。
  node->next = headnode->next;
  node->data = data1;
  headnode->next=node;
 }
 listlength = listlength + n;
 return 1;
}


template<typename T>

void myslist<T>::traversal()
{
 if (headnode->next == nullptr)
  cout << "该链表的长度为0" << endl;
 else
 {
  slistNode<T>* node = headnode;
  while (node->next != nullptr)
  {
   cout << "链表中的数据为" << ": "<<node->next->data<<endl;
   node = node->next;
  }
  cout << "\n输出完毕" << endl;
 }

}

template<typename T>
bool myslist<T>::isEmpty()
{
 if (headnode->next == nullptr)
 {
  cout << "链表已经空了" << endl;
  return true;
 }
 else
 {
  cout << "链表非空" << endl;
  return false;
 }
}

template<typename T>
void myslist<T>::Delete(T x)
{
 slistNode<T>* node= headnode;
 while (node->next != nullptr)
 {
  if (node->next->data == x)
  {
   slistNode<T>* node1 = node->next;
   node1 = node->next;
   node->next = node1->next;
   listlength = listlength - 1;
  }
  else
      node = node->next;
 }
 cout << "该链表没有该值" << endl;
}

template<typename T>
bool myslist<T>::insert(T x,int n)
{
 slistNode<T>* node = new slistNode<T>();
 if (node == nullptr)
 {
  cout << "动态内存分配失败" << endl;
  return 0;
 }
 node->next = headnode->next;//注意:这里将node=headnode是错误的,后者是将指针headnode赋给node,这会导致node与headnode指向同一个内存,
 //使得原先分配给node的内存泄漏,同时,导致travel时,由于headnode地址和Node一样,从而headnode->next==headnode
 if (n < 0)
 {
  cout << "你输入的位置不合理" << endl;
  return 0;
 }
 else if (n == 0)
 {
  node->data = x;
  headnode->next = node;
  return 1;
 }
 else if (n > listlength)
 {
  cout << "你输入的位置超过链表的长度" << endl;
  return 0;
 }
 else if (0 < n&&n < listlength)
 {
  if (node->next == nullptr)
  {
   cout << "你输入的位置不合理" << endl;
   return 0;
  }
  else
  {
   slistNode<T>* node1 = headnode;
   int i = 0;
   while (i < n)
   {
    node1 = node1->next;//不要给指向新节点的指针重新赋值,这回改变指针的地址,从而创建新节点的意图会失败。使用中间指针
    i++;
   }
   node->next = node1->next;
   node1->next = node;   
   node->data = x;
   return 1;
  }
 }
}

template<typename T>
bool myslist<T>::insertlast(T x)
{
 slistNode<T>* node = new slistNode<T>();
 if (node == nullptr)
 {
  cout << "动态内存分配失败" << endl;
  return 0;
 }
 if (headnode->next == nullptr)
 {
  headnode->next = node;
  node->data = x;
 }
 else
 {
  slistNode<T>* node1 = headnode;
  while (node1->next != nullptr)
  {
   node1 = node1->next;
  }
  node1->next = node;
  node->data = x;
  listlength = listlength + 1;
 } 
}

template<typename T>
slistNode<T>* myslist<T>::find(T x)
{
 slistNode<T>* node =headnode;
 if (node->next == nullptr)
 {
  cout << "该链表没有值:" << x<<endl;
 }
 else
 {
  int i = 0;
  while (node->next != nullptr)
  {
   i = i + 1;
   if (node->next->data == x)
   {
    cout << "链表中该值是第:" << i << "个位置" << endl;
    cout << "它的地址为:" << node << endl;
    return node;
   }
   else
    node = node->next;
  }
  cout << "该链表没有值:" << x << endl;
 }
}

//1,使用new动态分配内存的指针对象,不手动释放内存时,是不会调用析构函数的,但如果该类的对象是包含在另一个对象里面,则当另一个对象生命结束时,
//则会先调用该类的对象析构函数,再调用另一个对象的析构函数。
//2,将一个对象指针赋值为空,还是分配了内存的
//3,在对象释放之前,不要将其对应的指针赋值新指针。这会使得内存泄漏

//main.cpp

#include"List2.h"
#include<iostream>
using namespace std;
int main()
{
 {
 myslist<int> list;
 list.isEmpty();
 cout << "链表的长度为:" << list.length() << endl;
 int n;
 cout << "请输入链表首部插入数据的个数:";
 cin >> n;
 cout << endl;
 list.add(n);
 list.traversal();
 list.isEmpty();
 cout << "链表的长度为:" << list.length() << endl;
 cout << "请输入你想要在链表中寻找的值:";
 int n1;
 cin >> n1;
 cout << endl;
 slistNode<int>* b=list.find(n1);
 list.Delete(n1);
 cout << "在删除值:" << n1 << "后,链表的中的值为:";
 list.traversal();
 int m, n2;
 cout << "请输入你想插入链表中值的大小:";
 cin >> m;
 cout << endl;
 cout << "请输入你想插入链表中值的位置";
 cin >> n2;
 cout << endl;
 list.insert(m,n2-1);
 cout << "在插入新值"<<m<<"后,链表中的值为";
 list.traversal();
 int x;
 cout << "请输入你想在链表尾部插入值的大小:";
 cin >> x;
 cout << endl;
 list.insertlast(x);
 list.traversal();

  }
 system("pause");
 return 0;
}

菜鸟一只

猜你喜欢

转载自blog.csdn.net/qq_42498763/article/details/82956398