单链表:1、逻辑上连续,位置上可以不连续的存储方式。

2、单链表由无数个结点组成,每个结点由数据段和指针域组成,数据段存储数据,指针域存储后继的地址。

3、每个结点最多有一个前继和一个后继。

4、其中第一个结点没有前继,所以我们通常建立一个头结点来保存他的位置,其中头结点的数据段我们不关注。

5、最后一个结点没有后继,所以我们将最后一个结点的指针域赋为NULL.


//函数声明:"linklist.h"

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct linknode
{
	ElemType data;
	struct linknode *next;
}node;
void judgement_memory(node * p);                //判断动态内存是否开辟成功

node* creat_order();                //正向建立链表,尾插法
node * creat_reverse();             //反向建立链表,头插法

void insert(node *head, int i, ElemType x);     //在i位置上插入值为x的结点

void delete_place(node *head, int i);           //删除i结点
int delete_element(node *head, ElemType const x);       //删除第一个值为x的结点
void delete_all_element(node *ret, ElemType x);       //删除所有值为x的结点

void find_element(node *head, ElemType const x);     //寻找所有值为x的结点位置
void find_place(node *head, int i);                  //寻找i结点上的元素

void length_list(node *head);

void output(node *head);                              //打印链表

node* inits_linklist(node *head);                  //释放链表

void sortrank(node *head);                      //对链表进行排序

int means();




//函数实现:"linklist.c"

#include"linklist.h"
void judgement_memory(node * p)     //判断开辟内存是否成功
{
	if (NULL == p)
	{
		perror("out of memory:");
		exit(EXIT_FAILURE);
	}
}

node* creat_order()                    //建立一个具有头结点单链表,顺序插入(尾插法)
{
	printf("开始建立:");
	node *head, *p, *r;
	int x = 0;
	head = (node *)malloc(sizeof(node));             //建立头结点
	judgement_memory(head);
	r = head;
	while (1)
	{
		scanf("%d", &x);
		if (x != 0)                                        //以0作为链表结束标志
		{
			p = (node *)malloc(sizeof(node));
			judgement_memory(p);
			p->data = x;
			r->next = p;
			r = p;
		}
		else
			break;
	}
	r->next = NULL;
	printf("创建成功\n");
	return head;
}

node * creat_reverse()           //建立一个具有头结点的单链表,逆序输入(头插法)
{
	printf("开始建立:");
	node *head, *p, *r, *q;
	int x = 0;
	head = (node *)malloc(sizeof(node));
	judgement_memory(head);
	p = (node *)malloc(sizeof(node));                  //开辟最后一个结点
	judgement_memory(p);
	p->next = NULL;
	scanf("%d", &x);
	p->data = x; 
	r = head;
	q = p;
	r->next = q;
	while (1)
	{
		scanf("%d", &x);
		if (x!= 0)
		{
			p = (node *)malloc(sizeof(node));
			judgement_memory(p);
			p->data = x;
			r->next = p;
			p->next = q;
			q = p;
		}
		else
			break;
	}
	printf("创建成功\n");
	return head;
}

void insert(node *head, int i, ElemType x)                 //插入一个结点
{
	node *r;
	node *s = (node *)malloc(sizeof(node));
	judgement_memory(s);
	s->data = x;
		while (NULL != head&&i>1)    //要在第i个结点上插入,则先找到第i-1个结点
		{
			i--;
			head = head->next;
		}
		if (NULL != head&&i!=0)              //判断是不是头结点和结点是否存在
		{
			r = head->next;
			head->next = s;
			s->next = r;
			printf("插入成功\n");
		}
		else
			printf("结点不存在\n");
}


void delete_place(node *head, int i)                 //删除链表中一个指定位置的结点
{
	node *p;
	if (NULL == head)                                 
	{
		printf("链表下溢\n");
	}
	else
	{
			while (NULL != head&&i>1)            //找到第i-1个结点
			{
				i--;
				head = head->next;
			}
			if (NULL == head||i==0)
				printf("没有该位置\n");
			else
			{
				p = head->next;
				head->next = p->next;
				free(p);
				p = NULL;
				printf("删除成功\n");
			}
		 }
}


int delete_element(node *head, ElemType const x)   //删除链表中一个指定的x元素
{
	node *p, *q;
	if (head == NULL)                              //链表下溢,-1
		return -1;
	if (x == head->data)                           //判断第一个结点的数据是不是x
	{
		p = head;
		head = head->next;                          
		free(p);
		p = NULL;
		return 0;
	}
	else
	{
		while (NULL != head&&head->data != x)         //在链表剩下的元素中寻找x
		{
			q = head;
			head = head->next;
		}
		if (NULL == head)                              //没找到返回 0
			return 0;
		else
		{
			p = head;
			q->next = p->next;
			free(p);
			p = NULL;
		}
	}
	return 1;                                            //删除成功返回1
}
void delete_all_element(node *ret, ElemType x)       //根据元素删除,将这个链表里面的这个元素的结点全部删除
{
	int m = 0;
	int count = 0;
	while (1)
	{
		m = delete_element(ret, x);
		if (m == 0 || m == -1)
			break;
		count++;
	}
	if (m == 0)
	{
		if (count == 0)
			printf("没有此元素\n");
		else
			printf("删除成功\n");
	}
	else
		printf("链表下溢\n");
}

void find_element(node *head, ElemType const x)         //通过元素查找链表中该元素的位置找到返回结点
{
	head = head->next;                 //head是头结点,head->next指向下一个结点
	int count = 0;
	int i = 0;
	while (head)
	{
		count++;
		if (head->data == x)                            //如果找到输出count
		{
			i++;
			printf("元素位置:%d\n", count);
		}
		head = head->next;
	}
	if (i == 0)                         //如果没有输出count,说明没有x,所以i==0;
		printf("查询无果\n");
	else
		printf("\n");
}

void find_place(node *head, int i)              //通过位置来查找该链表中位于此位置的元素
{
	head = head->next;
	while (i>1)
	{                               //如果要找第i个结点的元素,则要先找到第i-1个结点
		i--;
		head = head->next;
		if (head->next == NULL)
			break;
	}
	if (i == 1)
		printf("结点元素:%d\n", head->data);
	else
		printf("查询无果\n");
}

void length_list(node *head)           //求链表长度
{
	head = head->next;
	int count = 0;
	while (head)
	{
		count++;
		head = head->next;
	}
	printf("链表长度:%d\n", count);
}

void output(node *head)                          //打印链表
{
	head = head->next;                            //让头结点指向下一个结点
	printf("输出链表:");
	while (head != NULL)
	{
		printf("%d  ", head->data);
		head = head->next;
	}
	printf("\n");
}

node* inits_linklist(node *head)    //初始化链表
{
	node *p,*r;
	p = head;
	while (p != NULL)
	{
		r = p;
		p = p->next;
		free(r);
		r = NULL;
	}
	head = NULL;
	p = NULL;
	printf("初始化成功\n");
	return head;
}

void sortrank(node *head)                                  //对链表进行排序
{
	node *p, *r;
	p = head->next;
	ElemType tmp;
	while (p != NULL)
	{
		r = head->next;
		while (r->next != NULL)
		{
			if ((r->data) > (r->next->data))
			{
				tmp = r->data;
				r->data = r->next->data;
				r->next->data = tmp;
			}
			r = r->next;
		}
		p = p->next;
	}
	printf("排序成功\n");
}

int means()                                     //选择方式
{
	int means = 0;
	while (1)
	{
		printf("请选择的方式:");
		scanf("%d", &means);
		if (means == 1 || means == 2)
			break;
		else
			printf("选择无效,请重新输入\n");
	}
	return means;
}




//函数测试:

#include"linklist.h"

int main()
{
	printf("*****************************************\n");
	printf("*****************************************\n");
	printf("**1.Creat_LinkList    2.Insert_Element **\n");
	printf("**3.Find              4.Delete_Element **\n");
	printf("**5.Length_LinkList   6.Output_LinkList**\n");
	printf("*7.InitsLinkLinst     8.Sortrank       **\n");
	printf("*0.Exit               *******************\n\n\n");

	node *ret=NULL;
	ElemType x;
	int i=0;
	int n = 0;
	while (1)                                      //循环起来,直到选择0结束
	{
		printf("请选择功能:");
		scanf("%d", &n);
		if (n == 0)
		{
			free(ret);
			exit(1);
		}
		if (n == 1 && ret == NULL)
		{                                        //选择正序建立链表还是逆序建立链表,并且链表以0作为结束标志
			printf("**1.creat_order  2.creat_reverse **\n");
			if (means() == 1)
				ret = creat_order();
			else
				ret = creat_reverse();
		}
		else if (n != 1&& ret == NULL)         //必须先建立链表,才能进行其他操作
			printf("请建立链表\n");
		else if (ret!=NULL&&n!=1)
		{
			switch (n)
			{
			case 2:
				printf("请输入要插入的位置和要插入的元素\n");
				scanf("%d", &i);
				scanf("%d", &x);
				insert(ret, i, x);
				break;
			case 3:                        //选择根据位置查找还是根据元素查找
			{
				 printf("**1.find_place         2.find_element **\n");
				 if (means() == 1)
				 {
					 printf("请输入要查找的位置:");
					 scanf("%d", &i);
				     find_place(ret, i);
				 }
				 else
				 {
				    printf("请输入要查找的元素:");
					scanf("%d", &x);
				    find_element(ret, x);
				}
			 }
				break;
			case 4:           //选择根据位置删除还是根据元素删除                   
			{
				printf("**1.delete_place     2.delete_element **\n");    
				if (means() == 1)
				{
					printf("请输入要删除的位置:");
					scanf("%d", &i);
					delete_place(ret, i);
				}
				else                                 
				{
					printf("请输入要删除的元素:");
					scanf("%d", &x);
					delete_all_element(ret, x);              //根据元素删除,将这个链表里面的这个元素的结点全部删除
				}
			}
				break;
			case 5:
				length_list(ret);
				break;
			case 6:                           //打印链表
				output(ret);
				break;
			case 7:                           //初始化链表,将链表制为空
				ret = inits_linklist(ret);
				break;
			case 8:
				sortrank(ret);
				break;
			default:
				printf("选择无效,请重新选择\n");
				break;
			}
		}
	 
	}
	system("pause");
	return 0;
}