(C语言)单链表各大操作(包含循环链表,双向链表)

单链表的建立

开头

首先这里介绍的建立单链表是有头结点的,因为对于带头结点的单链表,任何一个含有元素的结点都有前驱结点,在表的任何结点之前进行插入结点或删除结点,所要做的都是修改前一结点的指针域。若链表没有头结点,则首元素结点没有前驱结点,那么在其前面插入结点或删除该结点时操作会复杂些。

头插法:

思想:从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头结点之后,直至读入结束标志为止(以下例子结束标志为输入-1

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct LinkList
{
 int data;
 struct LinkList *next;
}Node;
//头插法建立单链表
Node *Create_Head()
{
   Node *L;
   Node *pNew;
   int x;
   L=(Node*)malloc(sizeof(Node));
   L->next=NULL;
   scanf("%d",&x);
   while(x!=-1)//表示输入-1结束
   {
    pNew=(Node*)malloc(sizeof(Node));
    pNew->data=x;
    pNew->next=L->next;//关键代码
    L->next=pNew;//关键代码
    scanf("%d",&x);
   }
   return L;
}
void Output(Node *L)
{
   Node *p;
   p=L->next;
   while(p)
 {
  printf("%d ",p->data);
  p=p->next;
 }
}
int main(void)
{
   Node *L;
   printf("开始建立单链表L,输入-1结束: \n");
   L=Create_Head();
   Output(L);
   return 0;
}

运行结果如图:

在这里插入图片描述
由运行结果易知由头插法建立的单链表的元素与输入元素顺序是颠倒的,头插法这一特性常运用于单链表的逆置

尾插法:

思想:与头插法不同,尾插法每次将创建的新结点插到当前单链表的表尾结点之后,所以要增加一个尾指针r,使之指向当前单链表的表尾。

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct LinkList
{
 int data;
 struct LinkList *next;
}Node;
//尾插法建立单链表
Node *Create_Tail()
{
 Node *L;
 Node *pNew,*r;
 int x;
 L=(Node*)malloc(sizeof(Node));
 L->next=NULL;
 r=L;
 scanf("%d",&x);
 while(x!=-1)
 {
  pNew=(Node*)malloc(sizeof(Node));
  pNew->data=x;
  //pNew->next=r->next;
  r->next=pNew;//关键代码
  r=pNew;//关键代码,尾指针移动
  scanf("%d",&x);
 }
 r->next=NULL;
 return L;
}void Output(Node *L)
{
   Node *p;
   p=L->next;
   while(p)
 {
  printf("%d ",p->data);
  p=p->next;
 }
}
int main(void)
{
   Node *L;
   printf("开始建立单链表L,输入-1结束: \n");
   L=Create_Tail();
   Output(L);
   return 0;
}

运行结果如图:
在这里插入图片描述
由运行结果易知由尾插法建立的单链表的数据与输入时候的数据顺序相同,因此尾插法常应用于单链表的合并

(尾插法建立单链表)无头结点

Node *Create_Tail() {
  Node *L = NULL;
  Node *pNew, *r;
  int x;
  r = L;
  scanf("%d",&x);
  while(x != -1) {
   pNew = (Node*)malloc(sizeof(Node));
   pNew->data = x;
   if (L == NULL) {
    L = pNew;
    r = pNew;
   } else {
  r->next = pNew;//关键代码
  r = pNew;//关键代码,尾指针移动
   }
   scanf("%d",&x);
  }
  r->next = NULL;
  return L;
}

应用

头插法应用:单链表就地逆置

尾插法应用:单链表的合并

#include <stdio.h>
#include "stdlib.h"

typedef struct linkList {
    int data;
    struct linkList *next;
}linkList;

//尾插法建立单链表
linkList *CreateList_Tail() {
    linkList *L, *pNew, *r;
    int x;
    L = (linkList *)malloc(sizeof(linkList));
    L->next = NULL;
    r = L;
    scanf("%d", &x);
    while (x != -1) {
        pNew = (linkList *)malloc(sizeof(linkList));
        pNew->data = x;
        pNew->next = r->next;
        r->next = pNew;
        r = pNew;
        scanf("%d", &x);
    }
    r->next = NULL;
    return L;
}
void Output(linkList *L) {
    linkList *p;
    p = L->next;
    while (p) {
        printf("%d\n", p->data);
        p = p->next;
    }
}

//头插法应用:单链表就地逆置
linkList *Reverse(linkList *L) {
    linkList *p, *q;
    p = L->next;
    L->next = NULL;
    while (p) {
        q = p;
        //注意这句话必须写在这里,不能写在结尾
        //原因自己可以画个图就知道了
        //如果写在结尾只能打印出一个值
        //提示:p只是一个指针。
        p = p->next;
        q->next = L->next;
        L->next = q;
    }
    return L;
}
//尾插法应用:单链表合并
linkList *MergeList(linkList *LA, linkList *LB) {
    linkList *pa, *pb, *pc, *r;
    pa = LA->next;
    pb = LB->next;
    LA->next = NULL;
    LB->next = NULL;
    pc = LA;
    r = pc;
    while (pa && pb) {
        if (pa->data <= pb->data) {
            r->next = pa;
            r = pa;
            pa = pa->next;
        } else {
            r->next = pb;
            r = pb;
            pb = pb->next;
        }
    }
    if (pa) {
        r->next = pa;
    } else {
        r->next = pb;
    }
    free(LB);
    return pc;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    linkList *LA, *LB, *LC;
    printf("建立第一个链表:\n");
    LA = CreateList_Tail();
    Output(LA);
    printf("建立第二个链表:\n");
    LB = CreateList_Tail();
    Output(LB);
    //逆置(头插法应用)
    //LA = Reverse(LA);
    //Output(LA);
    //合并(尾插法应用)
    LC = MergeList(LA, LB);
    Output(LC);
    
    return 0;
}


其他

循环链表

#import <Foundation/Foundation.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct LinkList {
    int data;
    struct LinkList *next;
}Node;
Node *Create_Tail(void);
//尾插法建立单链表
Node *Create_Tail() {
    Node *L;
    Node *pNew, *r;
    int x;
    L = (Node*)malloc(sizeof(Node));
    L->next = NULL;
    r = L;
    scanf("%d",&x);
    while(x != -1) {
        pNew = (Node*)malloc(sizeof(Node));
        pNew->data = x;
        //pNew->next=r->next;
        r->next = pNew;//关键代码
        r = pNew;//关键代码,尾指针移动
        scanf("%d",&x);
    }
    r->next = L;
    return r;
}
void Output(Node *L) {
    Node *p;
    p = L->next->next;
    while(p != L->next) {
        printf("%d ",p->data);
        p = p->next;
    }
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Node *L;
        printf("开始建立单链表L,输入-1结束: \n");
        L=Create_Tail();
        Output(L);
    }
    return 0;
}

在这里插入图片描述

双向链表

#import <Foundation/Foundation.h>

typedef struct Linklist {
    int data;
    struct Linklist *prev;
    struct Linklist *next;
}Linklist;

Linklist *CreateList() {
    Linklist *head, *p, *q;
    int x;
    head = (Linklist *)malloc(sizeof(Linklist));
    head->next = NULL;
    head->prev = NULL;
    p = head;
    scanf("%d", &x);
    while (x != -1) {
        q = (Linklist *)malloc(sizeof(Linklist));
        q->data = x;
        p->next = q;
        head->prev = q;
        q->prev = p;
        q->next = head;
        p = q;
        scanf("%d", &x);
    }
    return head;
}

//第一种遍历
void Output(Linklist *head) {
    Linklist *L = head->next;
    while (L != head) {
        printf("%d ", L->data);
        L = L->next;
    }
}
//第二种遍历
//void Output(Linklist *head) {
//    Linklist *L = head->prev;
//    while (L != head) {
//        printf("%d ", L->data);
//        L = L->prev;
//    }
//}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Linklist *LA;
        printf("开始创建单链表(输入-1结束):\n");
        LA = CreateList();
        Output(LA);
    }
    return 0;
}

链表排序(冒泡)

//这个是没有头结点。
//有头结点也很简单
//把 Node *p = L->next改成这样就行了。
void BubbleSort(Node *L) {
 for (Node *p = L; p != NULL; p = p->next) {
  for (Node *q = p->next; q != NULL; q = q->next) {
   if (p->data > q->data) {
    int t = q->data;
    q->data = p->data;
    p->data = t;
   }
  }
 }
 Output(L);
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值