本文主要是介绍用类模板封装链表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
闲来无聊,用类的模板封装的链表,记录下来,说不定哪天用得上那。
template <typename VALUE_TYPE>
class List{
public:
//定义节点类型
typedef struct Node
{
VALUE_TYPE data; //数据域
struct Node *next; //指针域:直接后继的指针
// struct Node *prior; //指针域:直接前驱的指针
} Node,*LINK_LIST;
private:
LINK_LIST ll; //链表的头指针
LINK_LIST tail; //尾节点指针
int size; //链表长度
public:
//构造函数:创建一个空链表(带头结点)
List()
{
ll=(struct Node*)malloc(sizeof(struct Node));
ll->next=NULL;
tail=ll;
size=0;
}
//析构函数:销毁链表
~List()
{
struct Node *p=ll,*q=NULL;
while(p!=NULL)
{
q=p->next;
free(p);
p=q;
}
ll=NULL;
tail=NULL;
size=0;
}
//判断链表是否为空
int IsEmpty()
{
return (int)(ll->next);
}
//获取链表长度,即节点个数
int GetLength()
{
/*
struct Node *p=ll->next;
int cnt=0;
while(p!=NULL)
{
cnt++;
p=p->next;
}
return cnt;
*/
return size;
}
//尾部插入节点
void Append(VALUE_TYPE v)
{
struct Node *q=(struct Node*)malloc(sizeof(struct Node));
q->data=v;
q->next=NULL;
tail->next=q;
tail=q;
size++;
/*
struct Node *p=ll;
while(p->next!=NULL)
{
p=p->next;
}
p->next=q;
*/
}
//头部插入节点
void InsertHead(VALUE_TYPE v)
{
struct Node *q=(struct Node*)malloc(sizeof(struct Node));
q->data=v;
q->next=ll->next;
if(ll->next==NULL) tail=q;
ll->next=q;
size++;
}
//在任意位置处插入节点
int Insert(int pos,VALUE_TYPE v)
{
struct Node *p=ll;
int i=0;
while(p!=NULL && i<pos-1)
{
p=p->next;
i++;
}
if(p==NULL || i>pos-1) return 0;
struct Node *q=(struct Node*)malloc(sizeof(struct Node));
q->data=v;
q->next=p->next;
p->next=q;
size++;
return 1;
}
//删除指定节点,根据节点索引(即节点位置,头结点的索引为0,第一个节点的索引为1,以此类推)
int Delete(int pos,VALUE_TYPE *v)
{
struct Node *p=ll;
int i=0;
while(p!=NULL && i<pos-1)
{
p=p->next;
i++;
}
//pos大于链表长度或小于1就失败返回
if(p==NULL || i>pos-1) return 0;
if(NULL!=v) *v=p->next->data;
if(p->next==tail) tail=p;
/*
struct Node *q=p->next->next;
free(p->next);
p->next=q;
*/
//和上面的处理等效
struct Node *q=p->next;
p->next=q->next;
free(q);
size--;
return 1;
}
//删除指定节点,根据节点的数据域,删除成功返回被删除节点的索引,否则返回0
int Delete(VALUE_TYPE v)
{
struct Node *p=ll;
int pos=1;
while(p->next!=NULL && p->next->data!=v) //此时&&的两个操作数不能颠倒位置
{
pos++;
p=p->next;
}
//如果没有找到满足条件的节点就失败返回
if(p->next==NULL) return 0;
if(p->next==tail) tail=p;
/*
struct Node *q=p->next->next;
free(p->next);
p->next=q;
*/
//和上面的处理等效
struct Node *q=p->next;
p->next=q->next;
free(q);
size--;
return pos;
}
//修改指定节点,根据索引
int UpdateByIndex(int pos,VALUE_TYPE v)
{
struct Node *p=ll;
int i=0;
while(p!=NULL && i<pos)
{
p=p->next;
i++;
}
//pos大于链表长度或小于1就失败返回
if(p==NULL || i>pos-1) return 0;
p->data=v;
return 1;
}
//修改指定节点,根据数据值
//修改成功返回被修改节点的索引,否则返回0
int UpdateByValue(VALUE_TYPE old_v,VALUE_TYPE new_v)
{
struct Node *p=ll->next;
int i=1;
while(p!=NULL && p->data!=old_v)
{
p=p->next;
i++;
}
if(p==NULL) return 0;
p->data=new_v;
return i;
}
//查找指定节点,根据索引获取数据值
VALUE_TYPE* GetElemByIndex(int index)
{
struct Node *p=ll;
int i=0;
while(p!=NULL && i<index)
{
p=p->next;
i++;
}
//pos大于链表长度或小于1就失败返回
if(p==NULL || i>index-1) return NULL;
return &(p->data);
}
//查找指定节点,根据数据值获取索引值
int GetElemByValue(VALUE_TYPE v)
{
struct Node *p=ll->next;
int i=1;
while(p!=NULL && p->data!=v)
{
p=p->next;
i++;
}
if(p==NULL) return 0;
return i;
}
//遍历链表
void Traverse(int(*visit)(VALUE_TYPE*))
{
struct Node *p=ll->next;
while(p!=NULL)
{
if(!visit(&(p->data))) break;
p=p->next;
}
}
//排序
//时间复杂度:O(n*n)
void Sort(int (__cdecl *compare )(const VALUE_TYPE &elem1, const VALUE_TYPE &elem2 ))
{
int i,j;
Node *p=NULL;
VALUE_TYPE v;
for(i=0;i<size-1;i++)
{
p=ll->next;
for(j=0;j<size-i-1;j++)
{
if(compare(p->data,p->next->data))
{
memcpy(&v,&(p->data),sizeof(VALUE_TYPE));
memcpy(&(p->data),&(p->next->data),sizeof(VALUE_TYPE));
memcpy(&(p->next->data),&v,sizeof(VALUE_TYPE));
}
p=p->next;
}
}
}
//逆序
//时间复杂度:O(n)
void Reverse()
{
/*
//算法一:相邻节点依次反向
Node* p=ll->next;
Node* q=p->next;
Node* t=NULL;
while(q!=NULL)
{
t=q->next;
q->next=p;
p=q;
q=t;
}
ll->next->next=NULL;
ll->next=p;
*/
//算法二:从第二个节点开始依次插入到链表头
Node* p=ll->next->next;
Node* q=NULL;
//逆序前的第一个节点处理后变为尾节点,所以它的next要赋值为NULL
ll->next->next=NULL;
while(p!=NULL)
{
q=p->next;
p->next=ll->next;
ll->next=p;
p=q;
}
}
//合并
//时间复杂度:O(1)
void Merge(List& l)
{
tail->next=l.ll->next;
tail=l.tail;
l.ll->next=NULL;
/*
Node *p=l.ll->next;
while(p!=NULL)
{
tail->next=p;
tail=p;
p=p->next;
}
*/
}
};
以上链表经本人测试没有问题。
这篇关于用类模板封装链表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!