3.1 单链表
3.1.1 定义

-  注: 元素离散的分布在存储空间中,所以单链表是非随机存取的存储结构。 即不能直接找到表中某个特定的结点,需要从表头开始遍历,依次查找。 
-  定义的代码 typedef struct LNode { ElemType data;//每个节点存放一个数据元素 struct LNode* next;//指向下一个节点 }LNode,*LinkList;
-  头结点和头指针  
-  初始化 分为带或不带头结点的初始化。 一般用带头结点的链表,会使后续操作方便。 -  不带头结点的初始化 bool InitList(LinkList &L) { L=NULL; return ture; }
-  带头结点的初始化 bool InitList(LinkList& L) { L = (LNode*)malloc(sizeof(LNode));//分配一个头节点 if (L == NULL)return false;//分配失败 L->next = NULL; return true; }
 
-  
3.1.2 建立
1)头插法建立单链表
在链表表头插入新结点。
-  步骤 1.将要插入结点的指针指向 原第一个结点; 2.将头结点指针指向 要插入的结点。 

//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
	LNode* s;
	int x;
	InitList(L);//初始化
	scanf_s("%d", &x);//输入结点值
	//插入表中
	while (x != 9999)//9999表示结束
	{
		//创建新结点
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;//新结点指针域指向原来的第一个结点
		//头结点指向新结点
		L->next = s;
		scanf_s("%d", &x);
	}
	return L;
}
2)尾插法建立单链表
在链表末尾插入新结点。
-  步骤 1.将尾结点的指针指向新结点; 2.更新尾指针(新尾指针变成新结点)。 

//尾插法建立链表
LinkList List_TailInsert(LinkList& L)
{
    LNode* s, * r = L;//r为表尾指针
    int x;
    scanf_s("%d", &x);//输入结点值
    //插入表中
    while (x != 9999)//9999表示结束
    {
        //创建新结点
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        //表尾指针指向新结点
        r->next = s;
        //更新表尾结点
        r = s;
        scanf_s("%d", &x);
    }
    r->next = NULL;//尾结点指针置空
    return L;
}
3.1.3 插入
-  步骤 1.查找插入位置的前驱结点; 2.将插入结点的指针 指向 插入位置的后驱结点; 3.将前驱结点的指针指向 插入结点。 
//在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList& L, int i, ElemType e)
{
	if (i < 1)return false;
	LNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while(p!=NULL&&j<i-1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}
3.1.4 删除
- 步骤

bool ListDelete(LinkList& L, int i, ElemType& e)
{
	if (i < 1)return false;
	LNode* p;//指针p指向当前扫描到的结点
	int j = 0;//当前p指向的是第几个结点
	//循环找到第i-1个结点
	p = L;//指向头结点
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	//i值不合法
	if (p == NULL||p->next==NULL)return false;
	LNode* q = p->next;//令q指向被删除结点
	e = q->data;//用e返回元素的值
	p->next = q->next;//将*q结点从链中断开
	free(q);//释放结点存储空间
	return true;
}
3.1.5 查找
1)按序号查找结点
//按序号查找结点
LNode* GetElem(LinkList L, int i)
{
	if (i < 1)return NULL;
	int j = 1;
	LNode* p = L->next;//第1个结点指针赋给p
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	return p;
}
2)按值查找结点
//按值查找
LNode* LocateElem(LinkList L, ElemType e)
{
	LNode* p = L->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	return p;
}
* 完整代码
#include<stdio.h>
#include <malloc.h>
#include<time.h>//用于生成随机数
#include<stdlib.h>
#define ElemType int
//---------------定义---------------
typedef struct LNode
{
	ElemType data;//每个节点存放一个数据元素
	struct LNode* next;//指向下一个节点
}LNode,*LinkList;
初始化不带头节点的单链表
//bool InitList(LinkList& L) {
//	L = NULL;
//	return true;
//}
不带会麻烦
//初始化带头节点的单链表
bool InitList(LinkList& L)
{
	L = (LNode*)malloc(sizeof(LNode));//分配一个头节点
	if (L == NULL)return false;
	L->next = NULL;
	return true;
}
//---------------建立单链表---------------
//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)
{
	int m;
	printf("\n1.手动输入\n2.自动生成\n");
	scanf_s("%d", &m);
	if (m == 1)
	{
		LNode* s;
		int x;
		scanf_s("%d", &x);//输入结点值
		//插入表中
		while (x != 9999)//9999表示结束
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = x;
			s->next = L->next;//新结点指针域指向原来的第一个结点
			//头结点指向新结点
			L->next = s;
			scanf_s("%d", &x);
		}
		return L;
	}
	else if (m == 2)
	{
		LNode* s;
		int n = 10;//结点个数
		srand(time(0));//初始化随机数种子
		while (n--)
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = rand() % 100 + 1;//随机产生100以内的数
			s->next = L->next;
			L->next = s;
		}
	}
	else
	{
		printf("请重新输入!\n");
		List_HeadInsert(L);
	}
	
}
//尾插法建立链表
LinkList List_TailInsert(LinkList& L)
{
	int m;
	printf("\n1.手动输入\n2.自动生成\n");
	scanf_s("%d", &m);
	if (m == 1)
	{
		LNode* s, * r = L;//r为表尾指针
		int x;
		scanf_s("%d", &x);//输入结点值
		//插入表中
		while (x != 9999)//9999表示结束
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = x;
			//表尾指针指向新结点
			r->next = s;
			//更新表尾结点
			r = s;
			scanf_s("%d", &x);
		}
		r->next = NULL;//尾结点指针置空
		return L;
	}
	else if (m == 2)
	{
		LNode* s,*r=L;
		int n = 10;//结点个数
		srand(time(0));//初始化随机数种子
		while (n--)
		{
			//创建新结点
			s = (LNode*)malloc(sizeof(LNode));
			s->data = rand() % 100 + 1;//随机产生100以内的数
			r->next = s;
			r = s;
		}
		r->next = NULL;
		return L;
	}
	else
	{
		printf("请重新输入!\n");
		List_TailInsert(L);
	}
}
//---------------插入-----------------
//在表L中的第i个位置上插入指定元素e
bool ListInsert(LinkList& L, int i, ElemType e)
{
	if (i < 1)return false;
	LNode* p;//指针指向当前扫描到的节点
	int j = 0;//当前p指向的是第几个节点
	//查找第i个位置
	p = L;//L指向头节点,头节点是第0个节点
	while(p!=NULL&&j<i-1)
	{
		p = p->next;
		j++;
	}
	if (p == NULL)
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}
//---------------删除----------------
bool ListDelete(LinkList& L, int i, ElemType& e)
{
	if (i < 1)return false;
	LNode* p;//指针p指向当前扫描到的结点
	int j = 0;//当前p指向的是第几个结点
	//循环找到第i-1个结点
	p = L;//指向头结点
	while (p != NULL && j < i - 1) {
		p = p->next;
		j++;
	}
	//i值不合法
	if (p == NULL||p->next==NULL)return false;
	LNode* q = p->next;//令q指向被删除结点
	e = q->data;//用e返回元素的值
	p->next = q->next;//将*q结点从链中断开
	free(q);//释放结点存储空间
	return true;
}
//---------------查找----------------
//按序号查找结点
LNode* GetElem(LinkList L, int i)
{
	if (i < 1)return NULL;
	int j = 1;
	LNode* p = L->next;//第1个结点指针赋给p
	while (p != NULL && j < i)
	{
		p = p->next;
		j++;
	}
	return p;
}
//按值查找
LNode* LocateElem(LinkList L, ElemType e)
{
	LNode* p = L->next;
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	return p;
}
void List_print(LinkList& L)
{
	LinkList t = L->next;
	while (t->next != NULL)
	{
		printf("%d,", t->data);
		t = t->next;
	}
	printf("%d\n", t->data);
}
void PutMenu()
{
	printf("\n----------菜单----------\n");
	printf("1.头插法创建单链表\n2 尾插法创建单链表\n");
	printf("3.插入元素\n");
	printf("4.删除元素\n");
	printf("5.按序号查找结点\n");
	printf("6.按值查找结点\n");
	printf("请选择想执行的操作:\n");
}
int main()
{
	LinkList L1;
	InitList(L1);
	//---------------菜单---------------
	PutMenu();
	int x;
	while (~scanf_s("%d", &x))
	{
		if (x == 1)
		{
			//头插法创建单链表
			List_HeadInsert(L1);
			List_print(L1);
		}
		else if (x == 2)
		{
			//尾插法创建单链表
			List_TailInsert(L1);
			List_print(L1);
		}
		else if (x == 3)
		{
			int pos, e;
			printf("请输入要插入的位置和元素:\n");
			scanf_s("%d %d", &pos, &e);
			ListInsert(L1, pos, e);
			List_print(L1);
		}
		else if (x == 4)
		{
			int pos, e;
			printf("请输入要删除的元素位置:\n");
			scanf_s("%d", &pos);
			ListDelete(L1, pos, e);
			printf("被删元素:%d\n",e);
			List_print(L1);
		}
		else if (x == 5)
		{
			LNode* p;
			int n;
			printf("请输入需要查找的序号:\n");
			scanf_s("%d", &n);
			p = GetElem(L1, n);
			printf("查找结点的值:%d", p->data);
		}
		else if (x == 6)
		{
			LNode* p;
			int n;
			printf("请输入需要查找的结点值:\n");
			scanf_s("%d", &n);
			p =LocateElem(L1, n);
			printf("success!");
		}
		PutMenu();
	}
	return 0;
}


















