数据结构(C语言)-- 单链表

文章目录

  • 前言
  • 一、要学什么、掌握什么
  • 二、深入了解
    • 1.数据构成
    • 2.头指针、头结点、首元结点
    • 2.空表
  • 二、链表的基本操作
    • 1、定义链表
    • 2、主函数(放最后面看)
    • 3、尾插入法建立带头结点的单链表
    • 4、按值查找结点
    • 5、删除带头结点的单链表
    • 6、打印链表
    • 7、删除所有结点
  • 四、总结
  • 五、完整代码


前言

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。


一、要学什么、掌握什么

1. 熟练掌握线性表的基本操作在链式存储结构上的实现
2. 掌握单链表的建立、插入、删除等基本操作;

二、深入了解

1.数据构成

数据域:存放数据本身的信息。
指针域:存放指向下个结点的地址(指向直接后继的指针)。
结点:数据元素的存储映像。由数据域和指针域两部分组成。

结点
这两部分信息(数据域和指针域)组成数据元素的存储结构,称之为“结点”。n个结点通过指针域相互链接,组成一个链表
数据结构(C语言)-- 单链表_第1张图片

2.头指针、头结点、首元结点

①头指针:永远指向链表中第一个结点的位置(如果链表有头结点,头指针指向头结点;否则,头指针指向首元结点)。
②头结点:一个不存任何数据的空结点,通常作为链表的第一个结点,它的数据域一般不存放数据。(头结点不是必须的。)
③首元结点:链表中第一个元素所在的结点,它是头结点后边的第一个结点。

数据结构(C语言)-- 单链表_第2张图片

注意头结点和头指针的区别:头指针是一个指针。。。。。头结点是一个实际存在的结点,它包含有数据域和指针域。

2.空表

①不带头结点的链表
     ----头指针为空
②带头结点的链表
     ----头结点指针域为空

二、链表的基本操作

1、定义链表

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"ctype.h"
typedef struct node          //定义结点
   {
	char data[10];             //结点的数据域为字符串
	struct node *next;      //结点的指针域
   }ListNode;
typedef ListNode* LinkList;         // 自定义LinkList单链表类型

LinkList CreatListR1(void);
ListNode *LocateNode(LinkList head, char *key);
void DeleteList(LinkList head,char *key);
void printlist(LinkList head);
void DeleteAll(LinkList head);

2、主函数(放最后面看)

//==========主函数==============
main()
{
  char ch[10],num[2];
  LinkList head;
  head=CreatListR1();          //用尾插入法建立单链表,返回头指针
  printlist(head);             //遍历链表输出其值
  printf(" Delete node (y/n):");  //输入"y"或"n"去选择是否删除结点
  scanf("%s",num); 
  if(strcmp(num,"y")==0 || strcmp(num,"Y")==0){ 
    printf("Please input Delete_data:");
    scanf("%s",ch);	        //输入要删除的字符串
    DeleteList(head,ch);
    printlist(head);
  }
  DeleteAll(head);            //删除所有结点,释放内存
}

3、尾插入法建立带头结点的单链表

-----什么是尾插法(元素插入链表尾部)

尾插法是从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点插入到当前链表的表尾上,直到读入结束标志为止。

数据结构(C语言)-- 单链表_第3张图片

  1. 先生成一个新结点S
  2. 尾指针指向新结点r->next=s
  3. r后移又变成最后一个结点
  4. r指针指向null
//==========用尾插入法建立带头结点的单链表===========
 LinkList CreatListR1(void)
 {
    char ch[10];
    LinkList head=(LinkList)malloc(sizeof(ListNode)); //生成头结点
    ListNode *s,*r,*pp;
    r=head;
    r->next=NULL;
    printf("Input # to end  ");  //输入"#"代表输入结束
    printf("Please input Node_data:");
    scanf("%s",ch);           //输入各结点的字符串
    while(strcmp(ch,"#")!=0) {         
         pp=LocateNode(head,ch);      //按值查找结点,返回结点指针
	 if(pp==NULL) {            //没有重复的字符串,插入到链表中
	    s=(ListNode *)malloc(sizeof(ListNode));
	    strcpy(s->data,ch);
		    r->next=s;
	    	r=s;
		    r->next=NULL;
         }
	    printf("Input # to end  ");
	    printf("Please input Node_data:");
		scanf("%s",ch);
    }
    return head;        //返回头指针
}

4、按值查找结点

//==========按值查找结点,找到则返回该结点的位置,否则返回NULL==========
ListNode *LocateNode(LinkList head, char *key)
{
    ListNode * p=head->next; //从开始结点比较
    while( p && (strcmp(p->data,key)!=0 ) ) //直到p为NULL或p->	data为key止
		p=p->next;        //扫描下一个结点
    return p;    //若p=NULL则查找失败,否则p指向找到的值为key的结点
}

5、删除带头结点的单链表

//==========删除带头结点的单链表中的指定结点=======
void DeleteList(LinkList head,char *key)
{ 
    ListNode *p,*r,*q=head; 
    p=LocateNode(head,key);    //按key值查找结点的 
   ********************
   if(p==NULL){
    	printf("error");
	}
	while(q->next!=p)
		q=q->next;
		r=q->next;
		q->next=r->next;
	free(r);
}

效果如下:根据输入(不允许输入重复的)的字符串,找到相应的结点并删除。

数据结构(C语言)-- 单链表_第4张图片

6、打印链表

//===========打印链表=======
void printlist(LinkList head)
{
    ListNode *p=head->next;       //从开始结点打印
    while(p){
	printf("%s,   ",p->data);
		p=p->next;
    }
    printf("\n");
}

7、删除所有结点

//==========删除所有结点,释放空间===========
void DeleteAll(LinkList head)
{
    ListNode *p=head,*r;
    while(p->next){
	r=p->next;
		free(p);
	p=r;
     }
     free(p);
}

四、总结

(1)找到要删除的这个节点:通过遍历来查找节点,从头指针+头节点开始,顺着链表依次找到我们要删除的那个节点。
(2)如果不是尾节点:首先把待删除节点的前一个节点的q->next指向待删除节点的后一个节点的首地址r->next,然后再将这个节点free掉。
(3)如果这个节点是尾节点,首先把待删除这个节点的前一个节点的q->next指针指向NULL,然后再将这个节点free掉。

五、完整代码

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"ctype.h"

typedef struct node          //定义结点
   {
	char data[10];             //结点的数据域为字符串
	struct node *next;      //结点的指针域
   }ListNode;
typedef ListNode* LinkList;         // 自定义LinkList单链表类型

LinkList CreatListR1(void);
ListNode *LocateNode(LinkList head, char *key);
void DeleteList(LinkList head,char *key);
void printlist(LinkList head);
void DeleteAll(LinkList head);
//==========主函数==============
main()

{
  char ch[10],num[2];
  LinkList head;
  head=CreatListR1();          //用尾插入法建立单链表,返回头指针
  printlist(head);             //遍历链表输出其值
  printf(" Delete node (y/n):");  //输入"y"或"n"去选择是否删除结点
  scanf("%s",num); 
  if(strcmp(num,"y")==0 || strcmp(num,"Y")==0){ 
    printf("Please input Delete_data:");
    		scanf("%s",ch);	        //输入要删除的字符串
    DeleteList(head,ch);
    		printlist(head);
  }
  DeleteAll(head);            //删除所有结点,释放内存
}
//==========用尾插入法建立带头结点的单链表===========
 LinkList CreatListR1(void)
 {
    char ch[10];
    LinkList head=(LinkList)malloc(sizeof(ListNode)); //生成头结点
    ListNode *s,*r,*pp;
    r=head;
    r->next=NULL;
    printf("Input # to end  ");  //输入"#"代表输入结束
    printf("Please input Node_data:");
    scanf("%s",ch);           //输入各结点的字符串
    while(strcmp(ch,"#")!=0) {         
         pp=LocateNode(head,ch);      //按值查找结点,返回结点指针
	 if(pp==NULL) {            //没有重复的字符串,插入到链表中
	    		s=(ListNode *)malloc(sizeof(ListNode));
	    strcpy(s->data,ch);
		    r->next=s;
	    r=s;
		    r->next=NULL;
         }
	    		printf("Input # to end  ");
	    printf("Please input Node_data:");
		    scanf("%s",ch);
    }
    return head;        //返回头指针
}
//==========按值查找结点,找到则返回该结点的位置,否则返回NULL==========
ListNode *LocateNode(LinkList head, char *key)
{
    ListNode * p=head->next; //从开始结点比较
    while( p && (strcmp(p->data,key)!=0 ) ) //直到p为NULL或p->	data为key止
		p=p->next;        //扫描下一个结点
    return p;    //若p=NULL则查找失败,否则p指向找到的值为key的结点
}
//==========删除带头结点的单链表中的指定结点=======
void DeleteList(LinkList head,char *key)
{ 
    ListNode *p,*r,*q=head; 
    p=LocateNode(head,key);    //按key值查找结点的 
    if(p==NULL){
    	printf("error");
    	exit(0);
	}
	while(q->next!=p)
		q=q->next;
	r=q->next;
	q->next=r->next;
	free(r);
}
//===========打印链表=======
void printlist(LinkList head)
{
    ListNode *p=head->next;       //从开始结点打印
    while(p){
	printf("%s,   ",p->data);
		p=p->next;
    }
    printf("\n");
}
//==========删除所有结点,释放空间===========
void DeleteAll(LinkList head)
{
    ListNode *p=head,*r;
    while(p->next){
	r=p->next;
		free(p);
	p=r;
     }
     free(p);
}

你可能感兴趣的:(数据结构与算法,链表)