C++课--单链表的基本操作

链表是一种重要的数据结构,能够动态地进行存储分配的一种结构链表,它与数组比较是不用事先确定存储空间,
链表的实现方式有两种(其实是我只会这两种)

第一种:是通过结构体指针实现。(课本上讲的就是这种方法)
第二种:是通过数组模拟实现。即链式向前星(不需要掌握)

这两种只是实现方式不同,本质是相同的;

下面讲解单链表如何实现:

首先链表的每个节点分为数据域和指针域

头指针Head指向第一个元素
第一个元素存储第一个数据和指针域指向第二个元素的地址 (第二个元素不必要紧挨着第一个元素)
第二个元素存储第二个数据和指针域指向第三个元素的地址
第三个元素存储第三个数据并且指针域指向空NULL

假设有三个元素:

a[0]包括数据部分 通过next指针指向a[1]的地址
a[1] 包括数据部分 通过next指针指向a[2]的地址
a[2] 包括数据部分 通过next指针NULL (一共三个元素,最后一个元素指向NULL)
最后一个元素中 next 指针域指向NULL

1.在数据域中可以定义多种数据类型并存放数据,
例如,char ,double ,int…
2.

链表的定义:

struct node{
    int data;         //数据域,所存的值 
    node *next;       //指针域,只想下一个元素 
};

创建头节点并初始化表头:

node*head,*pre,*p;
    head=new node;           //创造头结点 
    head->next=NULL;

假设将arr[ ]={}插入到链表

//链表的创建//
node* creatlist(int arr[],int len){    //建立链表 
    node*head,*pre,*p;        //头节点    尾结点    普通节点 
    head=new node;           //创造头结点 
    head->next=NULL;
    pre=head;                //pre赋值 ,pre指向于head; 
    for(int i=0;i<len;i++){
        p=new node;
        p->data=arr[i];      //赋值给数据域 
        p->next=NULL;         //最后一个节点的指针域置空 
        pre->next=p;          //新结点连到链表的结尾 ,上一个节点指向这个新结点 
        pre=p;                //pre指向链表的最后(新)一个结点 
    } 
    return head;
}
//链表的删除//
void del(node*head,int x){   //实现将链表所有数据域等于x的结点删除 
    node *pre,*p;
    pre=head;            //pre指针始终指向被删除结点的前置结点 
    p=pre->next;         //p指针为工作指针,用于遍历链表 
    while(p!=NULL){
        if(p->data ==x){          //如果是要被删除的结点 
            pre->next =p->next;    
            delete(p);             //要记得用过的内存还给操作系统 
            p=pre->next ;         //p指针更新到pre指针的后面 
        } 
        else {  
            pre=p;         //如果不是要删除的结点那么两个指针分别后移,这一步该为pre=pre->next; 
            p=p->next ;   
        }   
    } 
} 

完整代码:

#include<iostream>
#include<stdlib.h>

using namespace std;

//链表的定义//
struct node{
    int data;         //数据域 
    node *next;       //指针域,只想下一个元素 
}; 

//链表的创建//
node* creatlist(int arr[],int len){    //建立链表 
    node*head,*pre,*p;        //头节点    尾结点    普通节点 
    head=new node;           //创造头结点 
    head->next=NULL;
    pre=head;                //pre     对pre操作就是对head操作; 
    for(int i=0;i<len;i++){
        p=new node;
        p->data=arr[i];      //赋值给数据域 
        p->next=NULL;         //最后一个节点的指针域置空 
        pre->next=p;          //新结点连到链表的结尾 ,上一个节点指向这个新结点 
        pre=p;                //pre指向链表的最后(新)一个结点 
    } 
    return head;
}

//链表的插入//
void insert(node*head,int n,int x){       //实现将一个数据插入到链表的指定位置n处 
    node*p,*pre;
    pre=head;
    p=new node;      //分配新结点 
    p->data=x;
    while(--n){      //将pre指针定位到n位置的前面 
        pre=pre->next;
    }
    p->next=pre->next;    //先将pre的next赋值给p ,将pre所指结点后面所有的结点连接到p所指的结点 
    pre->next=p;          //将p所指的结点链接到pre所指结点后面。 
}

//链表的删除//
void del(node*head,int x){   //实现将链表所有数据域等于x的结点删除 
    node *pre,*p;
    pre=head;            //pre指针始终指向被删除结点的前置结点 
    p=pre->next;         //p指针为工作指针,用于遍历链表 
    while(p!=NULL){
        if(p->data ==x){          //如果是要被删除的结点 
            pre->next =p->next;    
            delete(p);             //要记得用过的内存还给操作系统 
            p=pre->next ;         //p指针更新到pre指针的后面 
        } 
        else {  
            pre=p;         //如果不是要删除的结点那么两个指针分别后移,这一步该为pre=pre->next; 
            p=p->next ;   
        }   
    } 
} 

//主函数//
int main()
{
    int arr[7]={2,0,2,1,6,9};         //这个是例子。 
    node*L=creatlist(arr,7),*p;
    insert(L,2,12);
    del(L,2);
    p=L->next;
    while(p!=NULL){
        printf("%d ",p->data);
        p=p->next; 
    }
    return 0;
}

链表
链表本身是离散化的,各点之间通过指针相连;
链表的每一结点都可存多种不同的数据类型每个结点都有一个指向
多次用到结构体,指针的操作,

1.顺序存储和链式存储
顺序表的存储空间是一次性分配的,且是连续的存储空间
链表的存储空间是多次分配的,不需要是连续的

2.插入删除时移动元素的个数
顺序表插入删除时需要移动近一半的元素(时间复杂度为O(n))
链表不需要移动元素,只需移动指针

null在值上等于零;
new开辟的空间在堆上,而一般声明的变量存放在栈上。通常来说,当在局部函数中new出一段新的空间,该段空间在局部函数调用结束后仍然能够使用

可用于存储图及对图进行一系列操作
例如昨天数据库老师讲的死锁的诊断—即判断链表是否存在环;

数组模拟链表

#include<iostream>
using namespace std;
int e[100010],head,ne[100010],idx;
//链表初始化;
void init(){
    head=-1;
    idx=0;
}
//向头部插入元素
void add_to_head(int x){
    e[idx]=x;
    ne[idx]=head;
    head=idx++;
}

void add(int k,int x){
    e[idx]=x;
    ne[idx]=ne[k];
    ne[k]=idx++;
}
void remove(int k){
   // if(k==0)head=ne[head];
      ne[k]=ne[ne[k]];
}
    for(int i=head;i!=-1;i=ne[i])cout<<e[i]<<" ";
    
    
    return 0;
    
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值