天天看点

向内存中连续存入数据_数据结构与算法||第十八节 链表

向内存中连续存入数据_数据结构与算法||第十八节 链表

链表与数组:

数组------>需要一段连续的内存空间来实现存储功能,对内存要求比较高!

链表------>不需要一段连续的内存空间,通过" 指针 "将零散内存单元串联!

图解链表与数组:

向内存中连续存入数据_数据结构与算法||第十八节 链表

单链表:

习惯把第一个结点叫作头结点,把最后一个结点叫作尾结点!

向内存中连续存入数据_数据结构与算法||第十八节 链表

链表的创建:

#includeusing namespace std;struct Node{    int data;//值域,存放数据值    Node *next;//指针域,存放指向下一个节点的地址};//结构体;号不能少//定义链表的头、尾以及游标指针Node *head,*tail,*p;int main(){    int n;    cin>>n;//存入链表的数据值    //第一步:初始化链表,头既是尾,尾既是头!    head=new Node;    tail=head;    //第二步:定义规则,实现链表创建    while(n!=-1){        p=new Node;        p->data=n;        //第三步:实现链接功能,新节点地址放入链表尾部当中的指针域        tail->next=p;        //第四步:链表尾巴向后移动        tail=p;        //第五步:链表尾巴地址域置空        tail->next=NULL;        //第六步:输入要保存的数据值,同时也是结束的标志        cin>>n;    }}
           

链表的遍历:

//第一步:拿到车头后第一个节点,链表需要从头开始遍历,通过指针域一个个遍历节点数据值p=head->next;//第二步:判断当前节点是否是尾节点while(p->next!=NULL){      cout<data<<"";      //第三步:节点向后移动      p=p->next;}//第四步:如果跳出循环说明遇到了尾节点,那么就需要把尾节点的数据值打印输出cout<data<
           

空链表危害:

如果什么数据值都没有保存,直接遍历,那么就会因为最开始没有对tail->next或者head->next没有进行初始化为NULL,造成指针域随机指向。

向内存中连续存入数据_数据结构与算法||第十八节 链表

链表的创建和遍历完整程序:

#includeusing namespace std;struct Node{    int data;//值域,存放数据值    Node *next;//指针域,存放指向下一个节点的地址};//结构体;号不能少//定义链表的头、尾以及游标指针Node *head,*tail,*p;int main(){    int n;    cin>>n;//存入链表的数据值    //第一步:初始化链表,头既是尾,尾既是头!    head=new Node;    tail=head;    //防止出现空链表    tail->next=NULL;    //第二步:定义规则,实现链表创建    while(n!=-1){        p=new Node;        p->data=n;        //第三步:实现链接功能,新节点地址放入链表尾部当中的指针域        tail->next=p;        //第四步:链表尾巴向后移动        tail=p;        //第五步:链表尾巴地址域置空        tail->next=NULL;        //第六步:输入要保存的数据值,同时也是结束的标志        cin>>n;    }    if(head->next!=NULL){    //第一步:拿到车头后第一个节点,链表需要从头开始遍历,通过指针域一个个遍历节点数据值    p=head->next;    //第二步:判断当前节点是否是尾节点    while(p->next!=NULL){          cout<data<<" ";          //第三步:节点向后移动          p=p->next;    }          //第四步:如果跳出循环说明遇到了尾节点,那么就需要把尾节点的数据值打印输出          cout<data<<endl;    }else{          cout<<"我是空链表"<<endl;    }}
           

功能测试空链表过滤:

向内存中连续存入数据_数据结构与算法||第十八节 链表

链表的插入:

向内存中连续存入数据_数据结构与算法||第十八节 链表

代码功能实现:

//如果想要实现插入x,那么需要明确前面的b(pre)和后面c(next)void insert_data(int v,int position){    Node *pre=head,*is;    int  k=0;//负责记录要插入的位置0或者1都行    //第一步:判断是否为空链表,如果为空链表那么直接插入    if(head->next!=NULL){         p=head;//1对应--->p=head->next;         //第二步:当前节点不是尾节点,那么遍历链表         while(p->next!=NULL){             k++;             //第三步:如果刚好适合插入,那么直接前后链接             if(k==position){                is=new Node;                is->data=v;                is->next=p;                pre->next=is;                break;             }else{                pre=p;                p=p->next;             }         }         //如果链表长度小于插入位置         if(k<5){           is=new Node;           is->data=v;           is->next=NULL;           pre->next=is;         }            }else{//否则插入位置是在尾部插入         is=new Node;         is->data=v;         is->next=NULL;         pre->next=is;    } }
           

链表的删除:

向内存中连续存入数据_数据结构与算法||第十八节 链表

代码功能实现:

//如果想要实现删除b,那么需要明确前面的a(pre)和后面c(next)void delete_data(int v){    Node *pre=head;    //第一步:判断是否为空链表    if(head->next!=NULL){          p=head->next;         //第二步:当前节点不是尾节点         while(p->next!=NULL){              //第三步:如果满足条件,那么删除p,pre直接和next链接              if(p->data==v){                 pre->next=p->next;                 delete p;                 p=pre->next;              }else{                 //如果不满足条件,那么p就成为了下一个pre,p->next就成为了下一个p                 pre=p;                 p=p->next;              }         }         //第四步:如果是尾节点         if(p->data==v){             delete p;             pre->next=NULL;         }    }else{         cout<<"我是空链表,不能完成删除!"<    } }
           

链表与数组的性能对比:

向内存中连续存入数据_数据结构与算法||第十八节 链表

其他链表类型:

循环链表:

向内存中连续存入数据_数据结构与算法||第十八节 链表

双向链表:

向内存中连续存入数据_数据结构与算法||第十八节 链表

双向循环链表:

向内存中连续存入数据_数据结构与算法||第十八节 链表

继续阅读