链表
来源:互联网 发布:阿里云服务器压力测试 编辑:程序博客网 时间: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();
}