单链表实现

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

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

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

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

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

函数声明部分:(linklist.h)
#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();
int length_list(node *head);
void find_element(node *head, ElemType const x);
void find_place(node *head, int i);
void insert(node *head, int i, ElemType x);
void delete_place(node *head, int i);
int delete_element(node *head, ElemType const x);
node* inits_linklist(node *head);
void output(node *head);
int means();
void delete_all_element(node *ret, ElemType x);
封装函数文件:(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;
	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;
	p->data = scanf("%d", &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;
	}
	return head;
}
int length_list(node *head)           //求链表长度
{
	int count = 0;
	while (head)
	{
		count++;
		head = head->next;
	}
	return count;
}
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  ", 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 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;
			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);
				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);
		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);
		}
	}
	return 1;                                            //删除成功返回1
}

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

void output(node *head)                          //打印链表
{
	head = head->next;                            //让头结点指向下一个结点
	printf("输出链表:");
	while (head != NULL)
	{
		printf("%d  ", head->data);
		head = head->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;
}
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");
}
主函数部分:
#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.Inits_LinkList    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);
		}
		//选择正序建立链表还是逆序建立链表,并且链表以0作为结束标志
		if (n == 1 && ret == NULL)
		{
			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请先建立链表\n\n");
		else if (ret!=NULL)
		{
			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:
				printf("链表长度:%d\n", length_list(ret));
				break;
			case 6:                           //打印链表
				output(ret);
				break;
			case 7:              //初始化链表,如果继续的话,需要重新建立链表
				ret = inits_linklist(ret);
				break;
			default:
				printf("选择无效,请重新选择\n");
				break;
			}
		}
	 
	}
	system("pause");
	return 0;
}


你可能感兴趣的:(实现,单链表)