数据结构--线性表(2)--链式存储(1)--单链表篇

线性表的链式表示和实现

1.线性链表

1).单链表定义线性表的思想

线性表的链式存储又称单链表。为了建立数据元素之间的线性关系,对每个链表节点,除存放自身数据外,还存放一个指向后继的指针。也称线性链表。

一个链表由n个节点组成。
单链表节点的结构特点:

datanext

data 为数据域部分,用于存储数据。 next 为指针域部分,用于指向后继。

指针为数据元素之间的逻辑关系的映像,则逻辑上相邻的两个元素其存储的物理位置不要求紧邻,因此这种存储结构为非顺序映像或链式映像。

利用单链表可以解决顺序表需要大量连续存储单元的缺点,由于单链表的元素离散地分布在存储空间中,所以单链表是非随机存取的存储结构,即不能直接找到表中某个特定元素,要查找某个元素,必须从表头开始遍历。

通常用头指针来标识一个单链表

带头节点的单链表
在这里插入图片描述

不带头节点的单链表
在这里插入图片描述

2).单链表定义线性表的结构体

typedef struct LNode{
int data;
struct LNode*next;  //定义后继节点
}LNode,*LinkList;

3).单链表定义线性表的基本操作

#建立新链表
头插法建立单链表

头插法思想:

带头节点:
把新节点插在头节点的后面。
操作:让新节点指针域指向头结点指针域指向的节点,再让头结点指针域指向新节点。


不带头结点:
把新节点插在头部。
操作:新节点指针域指向头指针指向的节点,再让头指针指向新节点。


带头节点,使用头插法建立新链表

/*带头节点建立新链表,头插法*/ 
LinkList Header_insert(LinkList &L)
{
	LNode *p; int x;
	L = (LinkList)malloc(sizeof(LNode));  //创建头节点 
	L->next = NULL;                       //指针域为空 
	printf("输入插入值:\n");               //输入要插入的数据 
	scanf("%d",&x);                       //若输入9999则创建空表 
	while(x != 9999)
	{
		p = (LNode *)malloc(sizeof(LNode));//创建一个新节点 
		p->data = x;                       //把元素放进数据域中 
		p->next = L->next;                 //指针域指向头节点指向的数据 
		L->next = p;                      //把头节点的指针指向新节点地址 
		printf("输入插入值(输入9999表示结束插入):\n");
		scanf("%d",&x);
	}
	return L;
 } 

不带头节点,使用头插法建立新链表

/*不带头节点,建立新链表,头插法*/
 LinkList UHeader_insert(LinkList &L)
{
	LNode *p; int x;
	printf("输入插入值(输入9999表示结束插入):\n");
	scanf("%d",&x);               
	while(x != 9999)
	{
		p = (LNode *)malloc(sizeof(LNode)); //创建一个新节点 
		p->data = x;                       //把数据装入新节点数据域
		p->next = L;                       //新节点指针域指向头指针指的数据地址 
		L = p;                             //头指针指向新节点(保持头指针一直指向头部)
		printf("输入插入值(输入9999表示结束插入):\n");
		scanf("%d",&x);
	}
	return L;
 } 

尾插法建立单链表

尾插法思想:

带头结点:
把新节点插在尾部。
定义一个尾指针,尾指针指向头节点,插入新节点,把最后一个节点指针域指向新节点,再让尾指针指向新节点,使尾指针始终指向尾部。


不带头结点:
尾指针指向头指针,头指针指向新节点,尾指针也指向这个新节点,也就是链表的第一个节点,再后面插入其他节点,让尾指针始终指向最后一个节点,这里操作和带头节点尾插法操作一样。


带头节点,使用尾插法建立链表

LinkList Tail_insert(LinkList &L)
  {
  	LNode *p,*r; //r为尾指针 
    int x;
	L = (LinkList)malloc(sizeof(LNode)); //创建一个新节点
	L->next = NULL;                      //指针域为空
	r = L;                               //尾指针指向头节点 
	printf("输入插入值:\n");
	scanf("%d",&x);           
	while(x != 9999)   
   {
	p = (LNode *)malloc(sizeof(LNode));//创建一个新节点
	p->data = x;                       //把数据装入新节点数据域
	r->next = p;                       //尾指针指针域指向新节点 
	r = p;                             //尾指针指向新节点(保持尾指针一直在最后一个节点) 
	printf("输入插入值(输入9999表示结束插入):\n");
    scanf("%d",&x);
   }
   r->next = NULL;                    //将尾指针指向节点中指针域置空  
   return L;
  } 

不带头节点,使用尾插法建立链表

/*******不带头节点,尾插法建立新链表*****************/ 
  LinkList UTail_insert(LinkList &L)
  {
  	LNode *p,*r; //r为尾指针 
    int x;
	r = L; 
	printf("输入插入值:\n");
	scanf("%d",&x); 
	while(x != 9999)
   {
	p = (LNode *)malloc(sizeof(LNode));//创建一个新节点
	p->data = x;   	  //数据域存入数据 
	p->next = NULL;   //指针域初始化为空 
	if(L == NULL)   //链表为空时 
	{
		L = p; //头节点指向新节点 
		r = L; //尾指针指向头节点 
	 } 
    else 
	{
    	r->next = p;
    	r = p;//保持尾指针始终指向尾部 
	}
	printf("输入插入值(输入9999表示结束插入):\n");
    scanf("%d",&x);
   }
   r->next = NULL;
   printf("带头节点,使用尾插法建立链表结束!\n"); 
   return L;
  } 

#查找操作
按序号查找结点值

按序号查找思想
带头结点:

  1. 判断给的序号是否为零,为零返回头节点。不为零从头结点的后继节点开始标记。
  2. 判断节点是否为空,节点不为空情况下,程序往下执行,查找对应序号的节点,返回该节点。若程序执行到节点为空,未找到对应序号的节点,说明查找的序号超出链表长度,序号不合法。返回为空。

不带头结点:

  1. 判断给的序号小于等于零,则序号不合法。
  2. 序号大于零就从第一个节点开始标记,节点不为空情况下,程序往下执行,查找对应序号的节点,返回该节点。若程序执行到节点为空,未找到对应序号的节点,说明查找的序号超出链表长度,序号不合法。返回为空。

带头节点代码如下

/*******按序号查找节点值************/ 
  LNode *GetElem(LinkList L,int i) //带头节点 
  {
  	int j = 1;          
  	LNode *p = L->next;//从头节点的下一个节点开始 
  	if(i == 0)        
  	    return L; //i==0返回头节点 
  	if(i < 1)
  	    return NULL;    //i无效返回NULL
    while(p && j < i) 
/*p不为空和j<i时继续循环,当其中一个不满足结束循环,
当是由p为空时结束循环,说明i值超过了链表长度 */ 
	{
		p = p->next;//p指向下一个节点 
		j++;       //标记序列 
	 } 
	 return p; //返回节点 
   } 

不带头节点的代码和带头节点的差异不大,就是从第一个节点开始,把LNode *p = L->next,改为LNode *p = L 即可。


按值查找表节点

按值查找节点思想:
带头结点:
从头结点后继节点开始查找,在节点不为空,节点数据域不是要查找的元素,继续往下一个节点查找。直到找到为止,返回找到的节点,若直到节点为空了,都没找到,则返回空。

不带头结点:从第一个节点开始查找,后面操作同带头结点的操作。


带头节点代码如下

LNode *GetElem_P(LinkList L,ElemType e) //带头节点 
  {
  	LNode *p = L->next;//从头节点下一个节点开始 
  	while(p != NULL && p->data != e) //节点不为空和节点数据域不等于要找的元素循环继续 
  		p = p->next;
  		return p; //找到后返回该节点指针,否则返回NULL 
   } 
    

不带头节点的代码和带头节点的差异不大,就是从第一个节点开始,把LNode *p = L->next,改为LNode *p = L 即可。


#插入节点操作
后插(在指定节点后面插入新节点)

后插思想:
在指定节点的后面插入新节点

bool insert_later(LinkList &L,ElemType a,ElemType e)//后插(在某节点位置后面插入)
  {
  	LNode *p,*q;
  	int temp;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中
  	p = GetElem_P(L,a);
  	if(p != NULL)  //判断查找节点是否存在
  	{
  		q->next = p->next;
  		p->next = q;
	  }
	  else
  	    return 0; //不存在查找的节点返回0
    return 1; //插入完成返回1
  }

扩展

/**在第i个位置后面插入元素**/
void insert_locationH(LinkList &L,int i,ElemType e)//在第i个位置后面插入元素 
  {
  	LNode *p,*q,*s;
  	int temp;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中 
 	p = GetElem(L,i-1);         //获取第i-1个位置节点 ,并使指针指向该节点 
 	s = p->next;               //使 s 指针指向第i个节点 
  	q->next = p->next;        //要插入的节点指针域指向i-1指向的下一个节点 
  	p->next = q;             //第i-1个节点指向插入节点 
	temp = s->data;          //交换数据域 
	s->data = q->data;
	q->data = temp;
  } 

上面代码也可不用这么多行,可以直接获取第i个节点,代码如下

void insert_locationH(LinkList &L,int i,ElemType e)//在第i个位置后面插入元素 
  {
  	LNode *p,*q;
  	int temp;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中 
 	p = GetElem(L,i);         //获取第i个位置节点 ,并使指针指向该节点 
  	q->next = p->next;        //要插入的节点指针域指向i-1指向的下一个节点 
  	p->next = q;             //第i个节点指向插入节点 
  } 

前插(在指定节点位置前面插入新节点)

前插思想:
在指定节点前面插入新节点

bool insert_pro(LinkList &L,ElemType a,ElemType e)//前插 (在某节点位置前面插入) 
  {
  	LNode *p,*q;
  	int temp;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中
  	p = GetElem_P(L,a);
	if(p != NULL)              //判断查找节点是否存在
	{
		q->next = p->next;
  		p->next = q;
  		temp = p->data;          //交换数据域 
	    p->data = q->data;
	    q->data = temp;
	}
	else
	return 0;  //不存在查找节点返回0
	return 1;  //插入完成返回1
   } 

在第i个节点之前插入新节点的代码与在第i个位置插入节点代码相同。


在第i个位置插入节点

在第i个位置插入节点思想:
找到第i-1个节点,对i-1个节点进行操作,要插入的节点指针域指向i-1指向的下一个节点,再使i-1个节点的指针域指向插入节点。

LinkList insert_location(LinkList &L,int i,ElemType e)//在第i个位置插入元素 
  {
  	LNode *p,*q;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中 
 	p = GetElem(L,i-1);         //获取第i-1个位置节点 ,并使指针指向该节点 
  	q->next = p->next;        //要插入的节点指针域指向i-1指向的下一个节点 
  	p->next = q;             //第i-1个节点指向插入节点 
  } 

#删除节点操作
按序列删除

按序列删除的思想:

1.判断i值是否合法,合法就找到被删除元素的前驱节点
2. 让前驱节点的指针域指向被删除节点的后继节点
3. 释放被删除的节点

//删除第i个节点
  bool Delete_i(LinkList &L,int i)//(带头节点)
  {
  	LNode *p,*q;
  	int k;
  	k = Lenght(L);
  	if(i > k && i < 1)  //判断i值是否合法 
  	return 0;
  	p = GetElem(L,i-1); //调用按序列查找函数,找到第i个节点的上一个节点并使p指向该节点
	q = p->next;       // q指向p的下一个节点,也就是要删除的节点 
	p->next = q->next; //被删除上一个节点指向被删除的下一个节点 
	free(q);          //释放节点的存储空间 
	return 1;

按值删除

按值删除思想(1)
找到被删除节点
让被删除节点和后继互换数据域,互换之后要删除的节点就是这个后继节点。
让找到的节点指针域指向后继节点的下一个节点。
最后释放交换数据时候后继节点。

 void Delete_P(LinkList &L,ElemType e)//(带头节点)
  {
  	LNode *p,*q;
  	p = GetElem_P(L,e);
  	q = p->next; 
    p->data = p->next->data; //被删除节点与后继节点交换数据域 
    p->next = q->next;      //互换之后的节点指针域指向后继节点的后继节点 
	free(q);               //释放交换后的节点的存储空间 
   } 

上述代码有个bug,就是当要删除的是最后一个节点,p->data = p->next->data;会出现下一个节点为空。【也就是p->next=NULL】,所以当要删除最后一个节点时要做额外处理。【本人太菜,想不到在不出现脏数据的情况下该怎么处理,于是才有下面第二种算法,上下两种算法时间复杂度相等】

按值删除思想(2)
在查找节点时,使用一个指针,使这个指针始终保持指向要被删除元素的前驱节点。
判断被删除节点指针域是否为空【其实就是判断是否是最后一个节点】。
不是最后一个节点,就让该节点的前驱节点的指针域指向被删除节点的后继节点。
是最后一个节点,就让被删除节点的前驱节点的指针域赋为空。
最后释放被删除节点。

 void Delete_P(LinkList &L,ElemType e)//(带头节点)
  {
  	LNode *q;
  	LNode *p = L->next;//从头节点下一个节点开始
  	while(p != NULL && p->data != e) //节点不为空和节点数据域不等于要找的元素循环继续 
  	{
  		q = p;      //使指针一直保持指向下一个节点的前驱节点 
  		p = p->next;
	}
	 if(p->next != NULL)   //当下一个节点不为空时,执行下面操作           
	    q->next = p->next; // 前驱节点指向被删除节点的后继节点
     else
	   q->next = NULL;   //当下一个节点为空时,对前驱指针指针域置空
	 free(p);          //释放节点的存储空间 
   } 

遍历链表
void PRINT_linklist1(LinkList L) //遍历单链表(带头节点) 
  {
  	LNode *p;
  	p = L;
  	while(p->next != NULL)  //看下一节点是否为空,为空结束遍历 
  	{
  		p = p->next;    //从头节点的下一个节点开始遍历 
  		printf("%d",p->data);
  		if(p->next != NULL)  //(打印格式)下个节点不为空,就打印-> 
  		printf("->");
	  }
   } 

不带头节点的代码和带头节点的差异不大,就是从第一个节点开始,把LNode *p = L->next,改为LNode *p = L 即可。


求表长
int Lenght(LinkList L)
  {
  	LNode *p;
  	int j = 0;
  	p = L->next;
  	while(p != NULL)  //节点为空终止循环
  	{
  		p = p->next;//指向下一个节点
  		j++;  //记录表长
	  }
	  return j;
  }

综合代码

根据自己需求编写调试的代码,函数模块与上面对比略有改动。

代码中建立链表是带头节点的。

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

typedef int ElemType; 

typedef struct LNode{      //定义单链表结构体 
	ElemType data;        //数据域 
	struct LNode *next;   //指针域 
}LNode,*LinkList;
/*带头节点建立新链表,头插法*/ 
LinkList Header_insert(LinkList &L)//带头节点 
{
	LNode *p; int x;
	L = (LinkList)malloc(sizeof(LNode));  //创建头节点 
	L->next = NULL;   //指针域为空 
	printf("输入插入值:\n"); //输入要插入的数据 
	scanf("%d",&x);  //若输入9999则创建空表 
	while(x != 9999)
	{
		p = (LNode *)malloc(sizeof(LNode));//创建一个新节点 
		p->data = x; //	把元素放进数据域中 
		p->next = L->next; //指针域指向头节点指向的数据 
		L->next = p;    //把头节点的指针指向新节点地址 
		printf("输入插入值(输入9999表示结束插入):\n");
		scanf("%d",&x);
	}
	printf("带头节点,使用头插法建立链表结束!\n"); 
	return L;
 } 
 /********带头节点建立新链表,尾插法***********/ 
  LinkList Tail_insert(LinkList &L)
  {
  	LNode *p,*r; //r为尾指针 
    int x;
	L = (LinkList)malloc(sizeof(LNode)); //创建一个新节点
	L->next = NULL;                      //指针域为空
	r = L;                               //尾指针指向头节点 
	printf("输入插入值:\n");
	scanf("%d",&x);           
	while(x != 9999)   
   {
	p = (LNode *)malloc(sizeof(LNode));//创建一个新节点
	p->data = x;                       //把数据装入新节点数据域
	r->next = p;                       //尾指针指针域指向新节点 
	r = p;                             //尾指针指向新节点(保持尾指针一直在最后一个节点) 
	printf("输入插入值(输入9999表示结束插入):\n");
    scanf("%d",&x);
   }
   r->next = NULL;                    //将尾指针指向节点中指针域置空 
   printf("带头节点,使用尾插法建立链表结束!\n"); 
   return L;
  } 
  int Lenght(LinkList L)
  {
  	LNode *p;
  	int j = 0;
  	p = L->next;
  	while(p != NULL)
  	{
  		p = p->next;
  		j++;
	  }
	  return j;
  }
  LNode *GetElem(LinkList L,int i) //带头节点 
  {
  	int j = 1;          
  	LNode *p = L->next;//从头节点的下一个节点开始 
  	if(i == 0)        
  	    return L; //i==0返回头节点 
  	if(i < 1)
  	    return NULL;    //i无效返回NULL
    while(p && j < i) 
/*p不为空和j<i时继续循环,当其中一个不满足结束循环,
当是由p为空时结束循环,说明i值超过了链表长度 */ 
	{
		p = p->next;//p指向下一个节点 
		j++;       //标记序列 
	 } 
	 return p; //返回节点 
   } 
   
   LNode * GetElem_P(LinkList L,ElemType e) //带头节点 
  {
  	LNode *p = L->next;//从头节点下一个节点开始
  	while(p != NULL && p->data != e) //节点不为空和节点数据域不等于要找的元素循环继续 
		  p = p->next;
  		return p; //找到后返回该节点指针,否则返回NULL 
   } 
   
   
   //删除第i个节点
  bool Delete_i(LinkList &L,int i)//(带头节点)
  {
  	LNode *p,*q;
  	int k;
  	k = Lenght(L);
  	if(i > k && i < 1)  //判断i值是否合法 
  	return 0;
  	p = GetElem(L,i-1); //调用按序列查找函数,找到第i个节点的上一个节点并使p指向该节点
	q = p->next;       // q指向p的下一个节点,也就是要删除的节点 
	p->next = q->next; //被删除上一个节点指向被删除的下一个节点 
	free(q);          //释放节点的存储空间 
	return 1;
   } 
    bool Delete_P(LinkList &L,ElemType e)//(带头节点)
  {
  	LNode *q;
  	LNode *p = L->next;//从头节点下一个节点开始
  	while(p != NULL && p->data != e) //节点不为空和节点数据域不等于要找的元素循环继续 
  	{
  		q = p;   //使指针一直保持指向下一个节点的前驱节点 
  		p = p->next;
	}
	if(p == NULL)//判断删除值是否在链表中 
  	return 0; 
	 if(p->next != NULL)   //当下一个节点不为空时,执行下面操作           
	    q->next = p->next; // 前驱节点指向被删除节点的后继节点
     else
	   q->next = NULL;           // 
	 free(p);          //释放节点的存储空间 
	 return 1;
   } 
   
    bool insert_pro(LinkList &L,ElemType a,ElemType e)//前插 (在某节点位置前面插入) 
  {
  	LNode *p,*q;
  	int temp;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中
  	p = GetElem_P(L,a);
	if(p != NULL)
	{
		q->next = p->next;
  		p->next = q;
  		temp = p->data;          //交换数据域 
	    p->data = q->data;
	    q->data = temp;
	}
	else
	return 0;
	return 1;
   } 
  bool insert_later(LinkList &L,ElemType a,ElemType e)//后插(在某节点位置后面插入)
  {
  	LNode *p,*q;
  	int temp;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中
  	p = GetElem_P(L,a);
  	if(p != NULL)
  	{
  		q->next = p->next;
  		p->next = q;
	  }
	  else
  	    return 0;
    return 1;
  }
  void insert_locationH(LinkList &L,int i,ElemType e)//在第i个位置后面插入元素 
  {
  	LNode *p,*q;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中 
 	p = GetElem(L,i);         //获取第i个位置节点 ,并使指针指向该节点 
  	q->next = p->next;        //要插入的节点指针域指向i-1指向的下一个节点 
  	p->next = q;             //第i个节点指向插入节点 
  } 
  
  bool insert_location(LinkList &L,int i,ElemType e)//在第i个位置插入元素 
  {
  	LNode *p,*q;
  	q = (LNode *)malloc(sizeof(LNode));//创建一个新节点
  	q->data = e;                 //把要插入的元素放入新节点中 
 	p = GetElem(L,i-1);         //获取第i-1个位置节点 ,并使指针指向该节点 
 	if(p == NULL)               //i值不合法返回空,当i值不和法返回0 
 	return 0;
  	q->next = p->next;        //要插入的节点指针域指向i-1指向的下一个节点 
  	p->next = q;             //第i-1个节点指向插入节点 
  	return 1;
  } 
   void PRINT_linklist1(LinkList L) //遍历单链表(带头节点) 
  {
  	LNode *p;
  	p = L;
  	while(p->next != NULL)  //看下一节点是否为空,为空结束遍历 
  	{
  		p = p->next;    //从头节点的下一个节点开始遍历 
  		printf("%d",p->data);
  		if(p->next != NULL)  //(打印格式)下个节点不为空,就打印-> 
  		printf("->");
	  }
	  printf("\n"); 
   } 
   int main()
   {
   	LNode *H,*W;
   	int n,a,k,j,b;
   	int g = 1;
   	LNode *p;
   	Tail_insert(W);//尾插法建立W链表
   	Header_insert(H);//头插法建立H链表 
   	PRINT_linklist1(W); //遍历建立好的链表
	PRINT_linklist1(H);
	printf("**********************选*择*操*作*****************************\n");
	printf("1.按序号擦找操作               2.按值查找操作\n");
	printf("3.按序号删除操作               4.按值删除操作\n");
	printf("5.按序号插入操作               6.遍历列表操作\n");
	printf("7.在某节点前面插入新节点操作   8.在某节点前面插入新节点操作\n");
	printf("*************************************************************\n");
	while(1)
	{
	printf("输入你想进行的操作(输入对应序号1-8):");
	scanf("%d",&n);
	if(n == 1) //1.按序号擦找操作
	{
		printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入序号(空格隔开)\n");
		scanf("%d %d",&k,&a);
		if(k == 1)
		{
		p = GetElem(W,a);
		printf("在 W 链表中第%d个节点数据域数据为%d\n",a,p->data); 
	   }
		else
		{ 
		p = GetElem(H,a);
		printf("在 H 链表中第%d个节点数据域数据为%d\n",a,p->data); 
		} 
		printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	}
	else if(n == 2) //2.按值查找操作
	{
		printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入查找值(空格隔开)\n");
		scanf("%d %d",&k,&a);
		if(k == 1)
	  {
		  p = GetElem_P(W,a);
		  if(p != NULL)
		      printf("W 链表中存在%d\n",p->data);
		  else
		      printf(" W 链表中不存在%d\n",a);
	  }	
		else
		{ 
	       p = GetElem_P(W,a);
		  if(p != NULL)
		       printf("H 链表中存在%d\n",p->data);
		  else
		      printf("H 链表中不存在%d\n",a);
		} 
		printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	}
	else if(n == 3)//3.按序号删除操作
	{
		printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入序号(空格隔开)\n");
		scanf("%d %d",&k,&a);
		if(k == 1)
		{
		j = Delete_i(W,a);
		 if(j == 0)
		 printf("删除失败\n");
		 else
		 printf("删除成功\n");
	   }
		else
		{ 
		j = Delete_i(H,a);
		if(j == 0)
		 printf("删除失败\n");
		 else
		 printf("删除成功\n");
		} 
		printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	 } 
	 else if(n == 4)//4.按值删除操作
	 {
	 	printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入删除值(空格隔开)\n");
		scanf("%d %d",&k,&a);
		if(k == 1)
		{
		j = Delete_P(W,a);
		 if(j == 0)
		 printf("链表中不存在%d\n",a);
		 else
		 printf("删除成功\n");
	   }
		else
		{ 
		j = Delete_P(H,a);
		if(j == 0)
		 printf("链表中不存在%d\n",a);
		 else
		 printf("删除成功\n");
		} 
	    printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	 } 
	 else if(n == 5)//5.按序号插入操作
	 {
	 	printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入序号和要插入的值(空格隔开)\n");
		scanf("%d %d %d",&k,&b,&a);
		if(k == 1)
		{
		j = insert_location(W,b,a);
		 if(j == 0)
		 printf("插入失败\n");
		 else
		 printf("插入成功\n");
	   }
		else
		{ 
		j = insert_location(H,b,a);
		if(j == 0)
		 printf("插入失败\n");
		 else
		 printf("插入成功\n");
		} 
	    printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	 }
	 else if(n == 6)//6.遍历列表操作
	 {
	 	printf("你想对那个链表操作 1.W  2.H\n");
		scanf("%d",&k);
		if(k == 1)
		PRINT_linklist1(W);
		else
		PRINT_linklist1(H);
		printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	 }
	 else if(n == 7)//7.在某节点前面插入新节点操作
	 {
	 	printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入指值和被插入的值(空格隔开)\n");
		scanf("%d %d %d",&k,&b,&a);
		if(k == 1)
		{
		j = insert_pro(W,b,a);
		 if(j == 0)
		 printf("插入失败\n");
		 else
		 printf("插入成功\n");
	   }
		else
		{ 
		j = insert_pro(H,b,a);
		if(j == 0)
		 printf("插入失败\n");
		 else
		 printf("插入成功\n");
		} 
	    printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	 }
	 else if(n == 8)  //8.在某节点后面插入新节点操作
	 {
	 	printf("你想对那个链表操作 1.W  2.H\n");
		printf("输入指值和被插入的值(空格隔开)\n");
		scanf("%d %d %d",&k,&b,&a);
		if(k == 1)
		{
		j = insert_later(W,b,a);
		 if(j == 0)
		 printf("插入失败\n");
		 else
		 printf("插入成功\n");
	   }
		else
		{ 
		j = insert_later(H,b,a);
		if(j == 0)
		 printf("插入失败\n");
		 else
		 printf("插入成功\n");
		} 
	    printf("是否继续对链表的操作(Y(1)/N(0))输入1或0:");
		scanf("%d",&g);
		if(g == 0)
		break;
	 }
	 else 
	 	printf("请输入正确操作\n");
	 }
	} 

脑图脑图

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

An安之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值