单链表-2

typedef struct Node {
    int data;//数据类型,可以换成任意数据类型,包括结构体struct等复合类型
    struct Node *next; //单链表的指针域
} Node,*LinkedList
//Node表示结点的类型,LinkedList表示指向Node结点类型的指针类型
    
    
//链表需要初始化操作
LinkedList listinit(){
    Node *L;
    L=(Node*)malloc(sizeof(Node));//开辟空间
     /*malloc()返回空指针类型,需要强制转换类型
         成为指针类型,故而出现了(Node*);*/

    if(L==NULL)(){
       printf("申请空间失败");
       //exit(0);
      //开辟空间失败可以考虑直接结束程序
     }//在C++中可以使用try-catch语句进行优化
    L->next=NULL; //指针指向空
}


//创建单链表(头插法)得到的结果是逆序的
/*该方法从一个空表开始,生成新结点,并将读取到的数据存放到新节点的数据域中,然后将新结点插入到当前链表的表头,即头节点之后*/
LinkedList LinkedListCreatH(){
    Node *L;
    L = (Node *)malloc(sizeof(Node));//申请头结点空间
    L-next = null;  //初始化一个空链表
    int x;                //x为链表数据域的数据
    while(scanf("%d",&x) != EOF){
        /*EOF(定义在stdio.h中的一个宏表示,表示-1,
        当缓冲区文件流满等问题发生时,scan的返回值为-1。
        */
        Node *p;
        p = (Node *)malloc(sizeof(Node)); //申请新的结点
        p->data = x;        //结点数据赋值
        p->next = L->next;      //将结点插入到表头L-->|2|-->|1|-->NULL
        L->next = p;
    }
    return L;
}

//创建单链表(尾插法)得到的结果是同序的
/*该方法是将新结点逐个插入到当前链表的表尾上,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点,否则就无法正确的表达链表*/
//尾插法建立单链表
LinkedList LinkedListCreatT(){
    Node *L;
    L = (Node *)malloc(sizeof(Node));   //申请头结点空间
    L->next = NULL;       //初始化一个空链表
    Node *r;           
    r = L;           //r始终指向终端结点,开始时指向头结点
    int x;            //x为链表数据域的数据
    while(scanf("%d",&x) != EOF){
        Node *p;
        p = (Node *)malloc(sizeof(Node)); //申请新的结点
        p->data = x;           //结点数据域赋值
        r->next = p;          //将结点插入到表头L-->|1|-->|2|-->NULL
        r = p;                
    }
    r->next = NULL;
    return L;
}

typedef struct Node {
    int data;//数据类型,可以换成任意数据类型,包括结构体struct等复合类型
    struct Node *next; //单链表的指针域
} Node,*LinkedList
//Node表示结点的类型,LinkedList表示指向Node结点类型的指针类型
    
    
//链表需要初始化操作
LinkedList listinit(){
    Node *L;
    L=(Node*)malloc(sizeof(Node));//开辟空间
     /*malloc()返回空指针类型,需要强制转换类型
         成为指针类型,故而出现了(Node*);*/

    if(L==NULL)(){
       printf("申请空间失败");
       //exit(0);
      //开辟空间失败可以考虑直接结束程序
     }//在C++中可以使用try-catch语句进行优化
    L->next=NULL; //指针指向空
}


//创建单链表(头插法)得到的结果是逆序的
/*该方法从一个空表开始,生成新结点,并将读取到的数据存放到新节点的数据域中,然后将新结点插入到当前链表的表头,即头节点之后*/
LinkedList LinkedListCreatH(){
    Node *L;
    L = (Node *)malloc(sizeof(Node));//申请头结点空间
    L-next = null;  //初始化一个空链表
    int x;                //x为链表数据域的数据
    while(scanf("%d",&x) != EOF){
        /*EOF(定义在stdio.h中的一个宏表示,表示-1,
        当缓冲区文件流满等问题发生时,scan的返回值为-1。
        */
        Node *p;
        p = (Node *)malloc(sizeof(Node)); //申请新的结点
        p->data = x;        //结点数据赋值
        p->next = L->next;      //将结点插入到表头L-->|2|-->|1|-->NULL
        L->next = p;
    }
    return L;
}

//创建单链表(尾插法)得到的结果是同序的
/*该方法是将新结点逐个插入到当前链表的表尾上,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点,否则就无法正确的表达链表*/
//尾插法建立单链表
LinkedList LinkedListCreatT(){
    Node *L;
    L = (Node *)malloc(sizeof(Node));   //申请头结点空间
    L->next = NULL;       //初始化一个空链表
    Node *r;           
    r = L;           //r始终指向终端结点,开始时指向头结点
    int x;            //x为链表数据域的数据
    while(scanf("%d",&x) != EOF){
        Node *p;
        p = (Node *)malloc(sizeof(Node)); //申请新的结点
        p->data = x;           //结点数据域赋值
        r->next = p;          //将结点插入到表头L-->|1|-->|2|-->NULL
        r = p;                
    }
    r->next = NULL;
    return L;
}

1.遍历单链表(打印,修改)

遍历的思路:建立一个指向链表L的结点,然后沿着链表L逐个向后搜索即可。

//遍历输出单链表
void printList(LinkedList L){
    Node *p=L->next;
    int i=0;
    while(p){
        printf("第%d个元素的值为:%d\n",++i,p->data);
        p=p->next;
    }
}

//链表内容的修改,在链表中修改值为x的元素变为k
LinkedList LinkedListReplace(LinkedList L,int x,int k){
    Node *p=L->next;
    int i=0;
    while(p){
        if(p->data==x){
            p->data=k;     //判断并修改
        }
        p=p->next; //继续遍历
    }
    return L;
}

简单的遍历设计的函数只需要void无参即可,而当涉及到修改操作时,可以设计一个LinkedList类型的函数,使其返回一个修改后的新链表

2.插入操作

链表的增加结点操作:

①查找到第i个位置;

②将该位置的next指针修改为指向新插入的结点

③新插入的结点next指针指向i+1位置的结点

操作方式:设置一个前驱结点,利用循环找到第i个位置,再进行插入

//单链表的插入,在链表的第i个位置插入x的元素
LinkedList LinkedListInsert(LinkedList L,int i,int x){
    Node *pre;            //pre为前驱结点
    pre = L;
    int tempi = 0;
    for(tempi = 1; tempi < i; tempi++){
        pre = pre->next;            //查找第i个位置的前驱结点
    }
    Node *p;                   //插入的结点为p
    p = (Node *)malloc(sizeof(Node));
    p->data = x;
    p->next = pre->next;
    pre->next = p;
    
    return L;
}

3.删除操作

删除元素要建立一个前驱结点和一个当前结点,当找到了需删除的数据时,直接使用前驱结点跳过要删除的结点指向要删除结点的后一个结点,再将原有的结点通过free函数释放掉。

//单链表的删除,在链表中删除值为x的元素
LinkedList LinkedListDelete(LinkedList L,int x){
    Node *p,*pre;         //pre为前驱结点,p为查找的结点
    p = L->next;
    
    while(p->data !=x){     //查找值为x的元素
        pre = p;
        p = p->next;
    }
    pre->next = p->next;   //删除操作,将其前驱next指向其后继
    free(p);
    
    return L;
}

自己学习用:搬运自:  单链表二 - 数据结构与算法教程 - C语言网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值