链表

来源:互联网 发布:阿里云服务器压力测试 编辑:程序博客网 时间:2024/05/22 10:36

************************************************************************/
/*  构造函数                                                                   
/***********************************************************************/
CSeqList::CSeqList()
{
 // 将顺序表初始化为0
  m_iLen = 0;
}

/************************************************************************/
/*     析构函数                                                               
/***********************************************************************/
CSeqList::~CSeqList()
{

}
/************************************************************************/
/* 将指定的数值插入顺序表中指定的位置   loc的取值是根据数组来取的既zero-based                                                                  
/***********************************************************************/
void CSeqList::InsertList(float num, int loc)
{
 int length = m_iLen;
 //判断表的空间是否足够
 if (MAXLEN==length)
 {
  cout << "空间已满,没有地方插入" << endl;
  return ;
 }
 //判断loc的合理性
 if (loc<0 || loc>length)
 {
  cout << "插入位置有误" <<endl;
  return;
 }
 //为即将插入的数据移出空位来
 while(length>loc)
 {
   m_iList[length] = m_iList[length-1];
  length -- ;
 }
 //放入数据,将游标加一
 m_iList[loc] = num;
 m_iLen++;


}
/************************************************************************/
/* 依次打印出顺序表中的当前各个元素                                                                   
/***********************************************************************/
void CSeqList::display()
{
 int i = 0;
 while (i < m_iLen)
 {
  cout << m_iList[i] << "  ";
  i ++;
 }
 cout <<endl;
}

/************************************************************************/
/*获得指定位置的数据 loc的取值是根据数组来取的既zero-based                                                                 
/***********************************************************************/
float CSeqList::GetNode(int loc)
{
 //检测获得位置的正确性,该值应该在[0,m_iLen)
 if (loc<0 || loc>=m_iLen)
 {
  cout << "所取数据位置有误" <<endl;
  return 0;
 }

 return m_iList[loc];
}

/************************************************************************/
/* 删除指定位置的数据     loc的取值是根据数组来取的既zero-based                                                                         
/***********************************************************************/
void CSeqList::DeleteNode(int loc)
{
 int length = m_iLen;
 //检测删除位置的正确性,该值应该在[0, m_iLen)
 if (loc<0 || loc>=length)
 {
  cout << "删除数据位置有误" <<endl;
  return ;
 }
 //while (loc+1<length)
 while (loc<length-1)
 {
  m_iList[loc] = m_iList[loc+1];
  loc++;
 }
 m_iLen--;

}

 

#include "SeqList.h"

void main()
{
 CSeqList mylist;
 for (int i=0; i<10; i++)
 {
  mylist.InsertList(i, i);
 }
 cout << "原始数据"<<endl;
 mylist.display();
 mylist.DeleteNode(4);
 cout << "删除后 " <<endl;
 mylist.display();
 
 
}

 

单链表:

//////////////////////////////////////////////////////////////////////////////////////////////

 

#include <iostream.h>
#include <stdlib.h>
#include <malloc.h>
class CSinLink
{
public:
 CSinLink();
 ~CSinLink();
 void InsertFromHead(float num);    //利用头插法插入数据
 void InsertFromTail(float num);    //利用尾插入法插入数据
 void DeleteFromHead(float num);    //利用头删法删除匹配数据
 void Display();        //从头至尾打印出各个数据
 int len;   
protected:
 typedef struct SINLINK
 {
  float num;
  SINLINK *next;

 }sinlink;
 sinlink *head;
 sinlink *tail;

};

 

#include "SinLinkList.h"

/************************************************************************/
/*构造函数     防止野指针                                                            
/***********************************************************************/
CSinLink::CSinLink()
{
 head = NULL;
 tail = NULL;
 len  = 0;

}

/************************************************************************/
/*析构函数  释放内存空间                                                                   
/************************************************************************/
CSinLink::~CSinLink()
{
 sinlink *willdel = NULL;
 while (head!=NULL)
 {
  willdel = head;
  head = head->next;
  free (willdel);
 }
 willdel = NULL;
}

/************************************************************************/
/*  利用头插法插入数据                                                                  
/***********************************************************************/
void CSinLink::InsertFromHead(float num)
{
 //分配内存,保存结点内容
 sinlink *tem = (sinlink*)malloc(sizeof(sinlink));
 tem->num = num;
 tem->next = NULL;
 //插入
 if (NULL==head)
 {
  //将头指针指向该结点或者说将头指针指向这一块内存
  head = tem;
  //因为是第一个结点,所以既是头结点也是尾结点,所以让尾指针也指向该结点
  tail = tem;
 }
 else
 {
  //将该结点指向当前头指针指向的元素
  tem->next = head;
  //将头指针指向该结点,从而使该结点成为第一个结点
  head = tem;
 }
 tem = NULL;
 len ++;
}

/************************************************************************/
/* 利用尾插法插入数据                                                                    
/***********************************************************************/
void CSinLink::InsertFromTail(float num)
{
 //创建临时指针,并分配插入结点的内存
 sinlink *tem =(sinlink*)malloc(sizeof(sinlink));
 tem->next = NULL;
 tem->num = num;

 //插入
 if (NULL==tail)
 {
  //因为是头一个结点,所以首尾指针同时指向该结点
  tail = tem;
  head = tem;
 }
 else
 {
  //将尾结点的下一个结点设置为当前分配的结点
  tail->next = tem;
  //当前结点成为了目前的最后一个结点,所以让尾指针指向它
  tail = tem;
 }
 tem = NULL;
 len++;
}

/************************************************************************/
/*  利用头删法删除匹配数据                                                                   
/***********************************************************************/
void CSinLink::DeleteFromHead(float num)
{
 bool bSuccess = false;
 int  total = 0;
 //分配了三个临时的指针 并初始化防止野指针
 sinlink  *tem = NULL;
 sinlink  *beftem = NULL;
 sinlink  *willdel = NULL;
 //将巡逻指针分配初始值
 tem = head;
 beftem = head;
 //以下为巡逻并删除匹配值的情况 要遵守几个原则
 //head值一定要时刻指向第一个结点,如果有的话
 //tail值一定要时刻指向最后一个结点
 //除非是头结点,否则beftem->next应该指向tem,也就是说befrem所指向的结点应该是tem所指向结点的直接前驱
 //willdel用来保存即将删除的结点,等到各个指针指向合适的位置后,就要收拾它了,之所以要这样一个指针,
 //是应了那句话“不是不报,时候未到”,这里应该叫"不是不删,时候未到",在重新组合了整个链后,自然就要删除它
 while(tem!=NULL)
 {
  //tem放置的是当前的结点,如果该结点的数据与需要删除的数据相匹配,则删除,但要区分是否为头结点,尾结点
  if(tem->num!=num)
  {
   beftem = tem;
   tem = tem->next;
  }
  else
  {
   willdel = tem;             //握住当前结点,便于调整好链接关系后删除
   //根据结点位置调整链表关系
   if (tem==head&&tem==tail)
   {
    tem = NULL;
    head = NULL;
    tail = NULL;
   }
   else if(tem==head)
   {
    head = head->next;     //重新调整链接关系 让头指针指向下一结点或者说让下一结点成为第一个结点
    tem = head;
    beftem = head;
   }
   else if (tem==tail)
   {
    tail = beftem;
    tail->next = NULL;
    tem = NULL;
   }
   else
   {
    tem = tem->next;
    beftem->next = tem;
   }
   //时候到了 删除结点 并完成登记工作
   free (willdel);
   willdel = NULL;
   bSuccess = true;           //标识找到了需要删除的结点
   total++;       //删除的数量加一
   len--;        //总的结点数量减一
  }
 }

 
 beftem = NULL;
 if (bSuccess)
 {
  cout << "你一共删除了" << total << "个元素" << num << endl;
 }
 
 
}

/************************************************************************/
/* 依次打印显示链表中的值                                                                    
/************************************************************************/
void CSinLink::Display()
{
 sinlink *tem;  //定义巡逻指针
 tem = head;    //将巡逻指针定位到头结点
 while(tem!=NULL)
 {
  cout << tem->num << "  ";
  tem = tem->next;
 }
 cout<<endl;
}

 

 

双链表:

#include <iostream.h>
#include <malloc.h>
class CDouLink
{
public:
 CDouLink();
 ~CDouLink();
 int len;
 void InsertFromHead(float num);
 void InsertFromTail(float num);
 void DeleteFromHead(float num);
 void DeleteFromTail(float num);
 void Display();
 
 
protected:
 typedef struct DOUBLELINK
 {
  float num;
  DOUBLELINK *prior;
  DOUBLELINK *next;
 }doulink;

 doulink *head;
 doulink *tail;
};

 

///////////////////////////////

 

#include "DoubleLink.h"

/************************************************************************/
/* 构造函数,完成类的初始化工作                                                                    
/***********************************************************************/
CDouLink::CDouLink()
{
 //防止野指针
 head = NULL;
 tail = NULL;
 //将链表的结点数量初始化
 len  = 0;
}

/************************************************************************/
/*  析构函数,完成类的结束工作                                                                   
/***********************************************************************/
CDouLink::~CDouLink()
{
 doulink *willdel;  //定义一个指向将被删除的结点的指针
 while(head!=NULL)
 {
  willdel = head;
  head = head->next;
  free(willdel);
 }
 //也可以用下面的代码完成各个结点的内存释放
 // while (tail!=NULL)
 // {
 //  willdel = tail;
 //  tail = tail->prior;
 //  free(willdel);
 // }
 
 willdel = NULL;
 
}

/************************************************************************/
/* 利用头插法将指定数据插入双向链表                                                                    
/***********************************************************************/
void CDouLink::InsertFromHead(float num)
{
 //建立将被插入的结点或者说在内存中为要插入的数据建立一个结点
 doulink *tem = (doulink*)malloc(sizeof(doulink));
 tem->num = num;
 tem->next = NULL;
 tem->prior = NULL;
 //根据是否具有头指针是否为空来完成插入的工作
 if (NULL==head)
 {
  head = tem;   //如果头指针为空,说明当前链表为空 则只要把头指针和尾指针都指向该
  tail = tem;  //结点就可以了,或者说该接既是第一个结点也是最后一个结点
 }
 else
 {
  //如果链表不为空 则调整链结构,将该结点链入链表的头部
  tem->next = head;  
  head->prior = tem;
  //将头指针指向该结点或者说将该结点设置为第一个结点
  head = tem;
 }
 
 len++;         //结点元素数量增加
 tem = NULL;
 
}

/************************************************************************/
/* 利用尾插发将指定数据插入双向链表                                                                    
/***********************************************************************/
void CDouLink::InsertFromTail(float num)
{
 //建立将被插入的结点或者说在内存中为要插入的数据建立一个结点
 doulink *tem = (doulink*)malloc(sizeof(doulink));
 tem->num = num;
 tem->next = NULL;
 tem->prior = NULL;
 //根据是否具有头指针是否为空来完成插入的工作
 if (NULL==head)
 {
  tail = tem;   //如果头指针为空,说明当前链表为空 则只要把头指针和尾指针都指向该
  head = tem;   //结点就可以了,或者说该接既是第一个结点也是最后一个结点
 }
 else
 {
  //如果链表不为空,则将该结点链入链表的尾部
  tail->next =tem;
  tem->prior = tail;
  //将尾指针指向该结点或者说将该结点设置为最后一个结点
  tail = tem;
  
 }
 len++;  //增加链表结点数量
 tem = NULL;
 
}

/************************************************************************/
/* 从头开始寻找并删除指定的数据                                                                    
/***********************************************************************/
void CDouLink::DeleteFromHead(float num)
{
 doulink *tem = head;    //定义巡逻指针
 doulink *willdel = NULL;   //用来保存将要被删除的结点
 bool    bSuccess = false;   //标识是否删除成功
 int    total = 0;     //标识一共删除了多少个匹配的数据
 
 while (tem!=NULL)
 {
  if(tem->num==num)
  {
   //握住将要被删除的结点
   willdel = tem;
   //根据是否是第一个结点,最后一个结点来调整链表的链关系或者说重新组装链
   if(tem==head&&tem==tail)
   {
    //如果只有一个结点,则直接清空链表就可以了
    head = NULL;
    tail = NULL;
    //直接将tem设置为NULL退出巡逻
    tem = NULL;
   }
   else if (tem==head)
   {
    //调整头指针,并调整第一个结点的前驱
    head = head->next;
    head->prior = NULL;
    //在所有分支当中都应该有逼近循环的语句
    tem = tem->next;
    
   }
   else if (tem==tail)
   {
    //调整尾指针,并调整最后一个结点的后继
    tail = tail->prior;
    tail->next = NULL;
    tem = tem->next;
    
   }
   else
   {
    tem->prior->next = tem->next;
    tem->next->prior = tem->prior;
    tem = tem->next;
   }
   
   //删除结点,完成记录工作
   free(willdel);
   bSuccess =true;
   total++;
   len--;
  }
  else
  {
   tem = tem->next;
  }
  
  
 }
 
 //如果有删除 输出提示信息
 if (bSuccess)
 {
  cout << "你一共删除了"  << total << "个数据" << num << endl;
 }
 
}

/************************************************************************/
/*从尾开始寻找并删除指定的数据                                                                     
/***********************************************************************/
void  CDouLink::DeleteFromTail(float num)
{
 doulink *tem = tail;    //定义巡逻指针
 doulink *willdel = NULL; //用来保存将要被删除的结点
 bool  bSuccess = false;  //标识是否成功删除
 int   total = 0;  //标识一共删除的结点个数
 
 while (tem!=NULL)
 {
  if (tem->num!=num)
  {
   tem = tem->prior;
  }
  else
  {
   willdel = tem; //握住将要删除的结点
   
   //根据结点的位置来调整链表关系
   if (tem==head&&tem==tail)
   {
    //如果只有一个结点,则直接清空链表就可以了
    head = NULL;
    tail = NULL;
    //直接将tem设置为NULL退出巡逻
    tem = NULL;
   }
   else if(tem==head)
   {
    //调整头指针,并调整第一个结点的前驱
    head = head->next;
    head->prior = NULL;
    //在所有分支当中都应该有逼近循环的语句
    tem = tem->prior;
   }
   else if(tem==tail)
   {
    //调整尾指针,并调整最后一个结点的后继
    tail = tail->prior;
    tail->next = NULL;
    tem = tem->prior;
    
   }
   else
   {
    tem->prior->next = tem->next;
    tem->next->prior = tem->prior;
    tem = tem->prior;
   }
   //删除结点,并完成登记工作
   free(willdel);
   bSuccess =true;
   total++;
   len--;
  }
 }
 
 
 //如果有删除 输出提示信息
 if (bSuccess)
 {
  cout << "你一共删除了"  << total << "个数据" << num << endl;
 }
}

/************************************************************************/
/* 从头结点开始依次打印显示出数据                                                                   
/***********************************************************************/
void CDouLink::Display()
{
 //定义巡逻指针
 doulink *tem;  
 tem = head;
 while(tem!=NULL)
 {
  cout << tem->num << "  ";
  tem = tem->next;
 }
 cout << endl;
 tem = NULL;
 
 
}


//////////////////////////

 

测试

 

#include "DoubleLink.h"
void main()
{
 CDouLink mylink;
 for(int i = 0; i<10; i++)
 {
  mylink.InsertFromHead(i);
  mylink.InsertFromTail(i+10);
 }
 mylink.InsertFromHead(19);
 cout << "删除前共有" << mylink.len << "个数字/n" ;
 mylink.Display();
 //mylink.DeleteFromHead(2);
 mylink.DeleteFromTail(19);
 cout << "删除后共有" << mylink.len << "个数字/n" ;
 mylink.Display();
 
}

 

 

 

原创粉丝点击