单向链表各种功能代码详解

      线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 与其直接后继数据元素 之间的逻辑关系,对数据元素 来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。由这两部分信息组成一个"结点"(如概述旁的图所示),表示线性表中一个数据元素。线性表的链式存储表示,有一个缺点就是要找一个数,必须要从头开始找起。


    笔者实现的各功能如下代码所示,主要为 插入、删除、查找、翻转。值得注意的是,在插入、删除、翻转的时候,要注意head指针的特殊情况。比如插入时,插入在第一个节点,删除时删除第一个节点。此时head指针指向的位置就要改变。另外,在实现功能的时候要注意head指针是否指向NULL。(本来还打算实现一个删除指定位置节点的,没做,也比较简单,有兴趣的自己试试吧!)

#include <iostream>
#include <string.h>
using namespace std;
//数据结构
struct Data
{
    int id;
    string a;
};
//节点结构
struct Node
{
    Data val;
    Node *next;
    Node(Data x):val(x),next(NULL) {}
};
class Linklist
{
public:
    Linklist();//构造函数
    ~Linklist();//析构函数
    void Insert(Data val,int pos=1);//插入函数 数据与插入位置,默认插入第一位
    void Remove1(Data val);//删除数据为val1的全部数据
    void findnode(Data val);//查找某个节点在链表中的所有位置
    void reverse();//翻转整个链表
    void print();//从头至尾打印
private:
    Node *head;//链表头部指针
    int length;//链表长度
};
Linklist::Linklist()
{
    head=NULL;
    length=0;
}
Linklist::~Linklist()
{//析构函数中head指针逐步后移,释放迭代中的p内存
    Node *p;
    for(int i=0;i<length;i++)
    {
        p=head;
        head=head->next;
        delete p;
    }
}
void Linklist::Insert(Data val, int pos)
{
    if(pos<1||pos-1>length)
    {//插入位置比第一个位置还小或者比总长度还大都是不应该存在的情况
        cout<<"insert error!"<<endl;
        return;
    }
    Node *p=head;
    Node *node=new Node(val);//生成一个新的节点
    if(pos==1)//插入在第一个位置的时候
    {
        node->next=p;
        head=node;
        length++;
        return;
    }
    int index=2;//移动到插入位置的前一位,指针p表示
    while (p!=NULL&&index<pos) {
        p=p->next;
        index++;
    }
    node->next=p->next;
    p->next=node;
    length++;
}
void Linklist::Remove1(Data val)
{
    //如果头结点是删除节点
    int flag=0;//1表示进行过删除操作
    if((head->val.id)==val.id)
    {
        head=head->next;
        length--;
        flag=1;
    }
    Node *p=head;
    Node *pr=head;//用pr指针指向删除点前一个节点
    while (p!=NULL) {
        if(p->val.id!=val.id)
        {
            pr=p;
            p=p->next;
        }
        else {
            pr->next=p->next;
            length--;
            p=p->next;//别忘了删除节点后p继续指向下一个位置,pr不动,还在p前一个节点
            flag=1;
        }
    }
    if(flag==0)
        cout<<"remove error!"<<endl;

}
void Linklist::findnode(Data val)
{
    if(head==NULL)
    {
        cout<<"print error!"<<endl;
        return;}
    Node *p=head;
    int index=1;//步长 表示目标位置
    int flag=0;//1表示链表中有这个数据
    while(p!=NULL)
    {
        if(p->val.id!=val.id)
        {
            p=p->next;
            index++;
        }
        else {
            cout<<"the pos is:"<<index<<endl;
            p=p->next;
            flag=1;
        }
    }
    if(flag==0){
        cout<<"no this data"<<endl;
    }
}
void Linklist::reverse()
{
    if(head==NULL)
    {
        cout<<"print error!"<<endl;
        return;}
    Node *p=head,*pn=head->next,*tempp;
    while(pn!=NULL)//这地方很绕,画个图好好想想吧···
    {
        tempp=pn->next;
        pn->next=p;
        p=pn;
        pn=tempp;
    }
    head->next=NULL;//别忘了head指针的处理
    head=p;
}
void Linklist::print()
{
    if(head==NULL)
    {
        cout<<"print error!"<<endl;
    return;}
    Node *p=head;
    while (p!=NULL) {
        cout<<p->val.id<<' '<<p->val.a<<endl;
        p=p->next;
    }
}
int main()
{
    Linklist list;
    Data val1,val2,val3,val4;
    val1.id=1;val1.a='a';val2.id=2;val2.a='b';val3.id=3;val3.a='c';
    val4.id=4;val4.a='d';
    list.Insert(val1,1);
    list.Insert(val2,2);
    list.Insert(val3,3);
    list.Insert(val4);//默认头部插入
    list.print();
    cout<<endl;
    list.Remove1(val1);
    list.print();
    list.findnode(val3);
    list.reverse();
    list.print();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41710905/article/details/79299694