• 数据结构之链表篇(单链表,循环链表,双向链表)C语言版


    1.链表

      链表是线性表的一种,由一系列节点(结点)组成,每个节点包含一个数据域和一个指向下一个节点的指针域。链表结构可以克服数组需要预先知道数据大小的缺点,而且插入和删除元素很方便,但是失去数组随机读取的优点。链表有很多种不同类型:单向链表,双向链表和循环链表。

    在链表中第一个节点叫头节点(如果有头节点)头节点不存放有效信息,是为了方便链表的删除和插入操作,第一个有效节点叫首节点,最后一个节点叫尾节点。

    2.单链表的操作

      链表的操作一般有创建链表,插入节点,删除节点,遍历链表。插入节点的方法有头插法和尾插法,头插法是在头部插入,尾插法是在尾部插入。

      下面以一个带头节点,采用尾插法的链表说明链表的各种操作。

      1 #include<stdio.h>
      2 #include<stdlib.h> 
      3 //单链表 
      4 
      5 
      6 //节点结构体 
      7 typedef struct node
      8 {
      9     int value;//数据域 
     10     struct node*next;//指针域 
     11 }Node;
     12 
     13 Node*createList();//创建链表并且返回头节点指针 
     14 void deleteNode(Node*head);//删除节点 
     15 void insertNode(Node*head);//插入节点 
     16 void travelList(Node*head);//遍历链表
     17  
     18 int main()
     19 {
     20     Node*head=createList();
     21     travelList(head);
     22     insertNode(head);
     23     travelList(head);
     24     deleteNode(head);
     25     travelList(head);
     26     return 0;
     27 }
     28 //创建链表,返回头节点指针 
     29 Node*createList()
     30 {    
     31     //采用尾插法 
     32     Node*head;//头节点 
     33     Node*tail;//尾节点 
     34     Node*temp=NULL;
     35     int i,value,size;
     36     head=(Node*)malloc(sizeof(Node));//头节点
     37     head->value=0;
     38     head->next=NULL;
     39     tail=head;
     40     printf("输入节点个数: ");
     41     scanf("%d",&size);
     42     printf("输入各个节点的值: ");
     43     
     44     for(i=0;i<size;i++)
     45     {
     46         scanf("%d",&value);    
     47         temp=(Node*)malloc(sizeof(Node)); 
     48         temp->value=value;
     49         tail->next=temp;//让尾节点的指针域指向新创建的节点 
     50         tail=temp;//尾节点改为新创建的节点 
     51         tail->next=NULL;//让尾节点的指针域为空 
     52     }
     53     return head;
     54 }
     55 //遍历链表 
     56 void travelList(Node*head)
     57 {    
     58     while(head->next!=NULL)
     59     {
     60         printf("%d
    ",head->next->value);
     61         head=head->next;
     62     }
     63 }
     64 //插入节点 
     65 void insertNode(Node*head)
     66 {
     67     int value;
     68     int position;
     69     int pos=0;
     70     Node*pre=NULL;//用来保存要插入节点的前一个节点 
     71     Node*newNode;
     72     printf("输入要插入节点的值: ");
     73     scanf("%d",&value);
     74     printf("要插入的位置: ");
     75     scanf("%d",&position);
     76     while(head!=NULL)
     77     {
     78         pos++;
     79         pre=head;
     80         head=head->next;
     81         if(pos==position)
     82         {    
     83             newNode=(Node*)malloc(sizeof(Node));
     84             newNode->value=value;
     85             newNode->next=pre->next;
     86             pre->next=newNode;
     87         }
     88     }
     89 }
     90 //删除节点 
     91 void deleteNode(Node*head)
     92 {    
     93     int value;
     94     Node*pre=head;
     95     Node*current=head->next;
     96     printf("输入要删除节点的值: ");
     97     scanf("%d",&value);
     98     while(current!=NULL)
     99     {    
    100         if(current->value==value)
    101         {
    102             pre->next=current->next;
    103             free(current);//释放空间 
    104             break;
    105         }
    106         pre=current;
    107         current=current->next;
    108     }
    109 } 

     3.循环链表

      循环链表就是让尾节点的指针域不再是NULL,而是指向头节点从而形成一个环。循环链表与单链表的操作没有多少差别,只是判断链表是否空应该是

      tail->next==head。

    4.双向链表

      双向链表的每一个节点都有两个指针域,一个前驱指针,指向前一个节点,头节点的前驱指针为NULL,一个后继指针,指向后一个节点,尾节点的后继指针为NULL。双向链表可以从任一个节点开始访问到前后节点,不像单链表只能向前。代码如下。

      1 #include<stdio.h>
      2 #include<stdlib.h> 
      3 //双向链表 
      4 typedef struct node
      5 {
      6     int value;//数据域 
      7     struct node* lNext;//前驱指针 
      8     struct node* rNext;//后继指针 
      9 }Node;
     10 
     11 Node*createList();//创建链表并且返回头节点指针 
     12 void deleteNode(Node*head);//删除节点 
     13 void insertNode(Node*head);//插入节点 
     14 void travelList(Node*head);//遍历链表
     15 
     16 int main()
     17 {
     18     
     19     Node*head=createList();
     20     travelList(head);
     21     insertNode(head);
     22     travelList(head);
     23     deleteNode(head);
     24     travelList(head);
     25     return 0;
     26 } 
     27 
     28 Node*createList()
     29 {
     30     Node*head,*tail,*temp;
     31     int num,value,i;
     32     head=(Node*)malloc(sizeof(Node));//头节点
     33     head->value=0;
     34     head->lNext=NULL;
     35     head->rNext=NULL; 
     36     tail=head;
     37     printf("输入节点个数: ");
     38     scanf("%d",&num); 
     39     printf("输入各个节点的值: ");
     40     for(i=0;i<num;i++)
     41     {    
     42         scanf("%d",&value);
     43         temp=(Node*)malloc(sizeof(Node));
     44         temp->value=value;
     45         temp->lNext=tail;
     46         tail->rNext=temp;
     47         tail=temp;
     48         tail->rNext=NULL;
     49     }
     50     return head;
     51 }
     52 
     53 
     54 void deleteNode(Node*head)//删除节点 
     55 {
     56     
     57     int value;
     58     Node*pre;
     59     Node*current=head->rNext; 
     60     printf("输入要删除节点的值: ");
     61     scanf("%d",&value);
     62     pre=head;
     63     while(current!=NULL)
     64     {
     65         if(current->value==value)
     66         {
     67             pre->rNext=current->rNext;//上一个节点指向下一个节点 
     68             current->rNext->lNext=pre;//下一个节点的前驱指针指向上一个节点 
     69             free(current);//删除该节点 
     70         }
     71         pre=current;
     72         current=current->rNext;
     73     }
     74 }
     75 
     76 void insertNode(Node*head)//插入节点 
     77 {
     78     Node*pre,*temp;
     79     int value,pos;
     80     int num=0;
     81     printf("输入要插入的值: ");
     82     scanf("%d",&value);
     83     printf("输入要插入的位置: ");
     84     scanf("%d",&pos);
     85     while(head!=NULL)
     86     {
     87         num++;
     88         pre=head;//保存上一个节点 
     89         head=head->rNext;//当前节点 
     90         if(pos==num)
     91         {
     92             temp=(Node*)malloc(sizeof(Node));
     93             temp->value=value;
     94             temp->lNext=pre;
     95             temp->rNext=head;
     96             head->lNext=temp;
     97             pre->rNext=temp;
     98         }
     99     }
    100 }
    101 
    102 void travelList(Node*head)//遍历链表
    103 {
    104     while(head->rNext!=NULL)
    105     {
    106         printf("%d
    ",head->rNext->value);
    107         head=head->rNext;
    108     }
    109 }

      其实只要弄懂单链表,其他也很简单的,无论链表多复杂,本质还是操作指针的指向,想想就会明白了。

      如果链表不会,后面的各种各样的树结构,就更不用学了。

  • 相关阅读:
    了解自我
    IT技能栈
    客户端的工作不仅仅只是看起来那么简单
    .NET 基础 一步步 一幕幕[XML基础操作]
    .NET 基础 一步步 一幕幕[Winform应用程序]
    .NET 基础 一步步 一幕幕[面向对象之堆、栈、引用类型、值类型]
    .NET 基础 一步步 一幕幕[面向对象之new、this关键字]
    .NET 基础 一步步 一幕幕[面向对象之静态、非静态]
    .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
    .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]
  • 原文地址:https://www.cnblogs.com/duichoumian/p/12836262.html
Copyright © 2020-2023  润新知