数据结构——单链表算法及完整操作

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#define Status int
#define ElemType int
using namespace std;

typedef struct LNode
{
	ElemType data;
	struct LNode * next;
}LNode, *LinkList;

/*****************基本操作函数**************/ 

//1.初始化链表——构造一个空表
//算法步骤:
//	1.生成新结点做头结点,用头指针L指向头结点
//	2.将头结点的指针域置空 
Status InitList(LinkList &L)
{
	L = new LNode;        //生成头结点 
	L->next = NULL;		  //将头结点指针域置空 
	return 1;
}

//2.判断链表是否为空
//空表的定义:链表中无元素(头指针和头结点仍然存在)
//算法思路:判断头结点指针域是否为空 
int ListEmpty(LinkList L)		//空表返回1,非空返回0 
{
	if (L->next)
		return 0;
	else
		return 1;
} 

//3.销毁单链表
//算法思路:从头指针开始,依次释放所有结点
Status DestroyList(LinkList &L)
{
	LinkList p;
	while (L)
	{
		p = L;			//p指向头结点 
		L = L->next;	//L指向下一结点 
		delete p;		//删除结点 
	}
	return 1;
} 

//4. 清空链表
//定义:链表仍然存在,但链表中无元素,成为空链表
//算法思路:依次释放所有结点,并将头指针指针域置空 
Status ClearList(LinkList &L)
{
	LinkList p, q;
	p = L->next;
	while (p)
	{
		q = p->next;
		delete p;
		p = q;
	}
	L->next = NULL;		//头结点指针域置空 
	return 1;
} 

//5.获取单链表长度
//算法思路:从首元结点开始,依次计数所有结点 
int ListLength(LinkList L)
{
	LinkList p;
	p = L->next;		//p指向首节点
	int i = 0;
	while (p)		//遍历链表,统计节点数 
	{
		p = p->next;
		i++;
	} 
	return i;
} 


//6. 取第i个元素的值
//算法步骤:
//	1.从第1个结点(L->next)顺序扫描,用指针p指向当前扫描到的结点p的初值为p=L->next.
//	2.j做计数器,累计当前扫描过的节点数,j的初值为1
//	3.当p指向扫描到的下一结点时,计数器j加1
//	4.当j==i时,p所指向的结点就是要找的第i个结点 
Status GetElem(LinkList L, int i, ElemType &e)
{
	LinkList p;
	p = L->next;
	int j = 0;
	while (p && j<i)	//向后遍历,直到p指向第i个元素或p为空 
	{
		p = p-> next;
		++j;
	}
	if (!p || j>i)	//第i个元素不存在	
		return 0;
	e = p->data;
	return 1;
} 

//6.查找
//算法步骤:
//	1.从第一个结点起,依次和e相比较
//	2.如果找到一个其值与e相等的数据元素,则返回其在链表中的位置或地址 
// 	3.如果查遍整个链表都没有和e相等的元素,则返回0或者NULL 
//
//6-1.查找——返回地址 
LNode *LocateElem(LinkList L, ElemType e)
{
	LinkList p;
	p = L->next;
	while (p && p->data != e)
	{
		p = p->next;
	}
	return p;
}

//6-2.查找——返回位置序号
//int LocateElem(LinkList L, ElemType e)
//{
//	LinkList p;
//	p = L->next;
//	int j = 1;
//	while (p && p->data != e)
//	{
//		p = p->next;
//		j++;
//	}
//	if (p)
//		return j;
//	else
//		return 0;
//} 

//7.插入结点
//算法步骤:
//	1.首先找到ai-1的存储位置p
//	2.生成一个数据域为e的新节点s
//	3.插入新节点:1.新节点的指针域指向ai(s->next = p->next)
//				  2.结点ai-1的指针域指向新节点
Status ListInsert(LinkList &L, int i, ElemType e)
{
	LinkList p, s;
	p = L;
	int j = 0;
	
	while (p && j < i-1)	//寻找第i-1个结点,p指向第i-1个结点	
	{
		p = p->next;
		++j;
	}
	
	if (!p || j > i-1)	//i大于表长+1或者小于1,位置非法 
		return 0;
		
	s = new LNode;	//生成结点s 
	s->data = e;
	s->next = p->next;	//将s插入链表中 
	p->next = s;
	return 1;
}

//8.删除第i个结点
//算法步骤:
//	1.首先找到ai-1的存储位置p,保存要删除的a的值
//	2.令p->next指向ai+1 
Status ListDelete(LinkList &L, int i, ElemType &e)
{
	LinkList p = L;
	LinkList q;
	int j = 0;
	while (p->next && j < i-1)	//寻找第i个结点,并令p指向其前驱 
	{
		p = p->next;
		++j;
	}
	if (!(p->next) || j > i-1)	//删除位置不合理 
		return 0;
	q = p->next;			//临时保存被删结点的地址以备释放 
	p->next = q->next;		//改变被删结点前驱结点指针域 
	e = q->data;			//保存被删结点数据域 
	delete q;				//释放结点空间 
	return 1;
}

//9.头插法建立链表
//算法步骤:
//	1.从一个空表开始,重复读入数据
//	2.生成新节点,将读入数据存放到新结点数据域中
//	3.从最后一个结点开始,依次将各结点插入链表前端
void CreatList_L(LinkList &L, int n)
 {
 	LinkList p;
 	L = new LNode;
 	L->next = NULL;		//先建立一个带头结点的单链表 
 	
 	for (int i = n; i > 0; --i)
 	{
 		p = new LNode;	//生成新节点 
 		cin >> p->data;
 		p->next = L->next;		//插入到表头 
 		L->next = p;
 	}
 }

//10.尾插法建立链表
//算法步骤:
//	1.从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点
//	2.初始时,r和L同时指向头结点,每读入一个数据新生成一个结点
//	将新结点插到尾结点后,r指向新结点 
void CreatList_R(LinkList &L, int n)
{
	LinkList r, p;
	L = new LNode;
	L->next = NULL;
	r = L;				//尾指针指向头结点 
	
	for (int i = 0; i < n; ++i)
	{
		p = new LNode;
		cin >> p->data;
		p->next = NULL;
		r->next = p;		//插入到表尾 
		r = p;				//r指向新的尾结点 
	}
}

/*****************功能函数**************/ 

//遍历输出函数 
void PrintList(LinkList L)
{
	LinkList p = L->next; 		//跳过头结点 
	if(ListLength(L))
	{
		printf("当前单链表所有元素:");
		while(p)
		{
			printf("%d ",p->data);
			p=p->next;
		}
		printf("\n");
	}
	else
	{
		printf("当前单链表已空!\n");
	}
}

//建立链表函数
void Create(LinkList &L)
{
	int n = 5;
	printf("请输入链表的长度:");
	scanf("%d",&n);
	printf("请输入链表的数据:"); 
	CreatList_R(L, n);			//尾插 
	if( ListEmpty(L) ) 
	{
		printf("建表失败!!!\n");	
	}
	else
	{
		printf("建表成功!!!\n");
//		PrintList(L); 
	}
}

//插入功能函数,调用ListInsert函数 
void Insert(LinkList &L)
{
  int place;
  ElemType e;
  bool flag;
  printf("请输入要插入的位置(从1开始)及元素:\n");
  scanf("%d %d", &place, &e);
  flag=ListInsert(L,place,e);
  if(flag) 
  {
	printf("插入成功!!!\n");
//	PrintList(L);
  }
}

//删除功能函数 调用ListDelete删除
void Delete(LinkList L)
{
  int place, e;
  bool flag;
  printf("请输入要删除的位置(从1开始):\n");
  scanf("%d",&place);
  flag=ListDelete(L, place, e);
  if(flag) 
  {
	printf("删除成功!!!\n");
	printf("删除的元素是 :%d\n", e);
//	PrintList(L);
  }
}

//查找函数

void Search(LinkList L)
{
	ElemType e;
	LNode *q;
	printf("请输入要查找的值:\n");
	scanf("%d",&e);
	q=LocateElem(L,e);
	if(q) 
	{
		printf("找到该元素!\n");
	}
	else
		printf("未找到该元素!\n");
}

void menu()
{
   printf("********1.建表    2.输出*********\n");
   printf("********3.插入    4.删除*********\n");
   printf("********5.查找    6.退出*********\n");
}

int main()
{

	LinkList L;
	int choice;
	InitList(L);
	while(1)
	{
		menu();
		printf("请输入菜单序号:\n");
		scanf("%d",&choice);
		if(choice==6) break;
		switch(choice)
		{
			case 1:Create(L);break;
			case 2:PrintList(L);break;
			case 3:Insert(L);break;
			case 4:Delete(L);break;
			case 5:Search(L);break;
			default:printf("输入错误!!!\n");
		}
	}

	return 0;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值