【2.3】链式单链表

一、单链表的结构特征

1、采用指针链接一些列的存储单元来存储数据

2、动态分配存储空间

3、插入或删除元素效率高

4、查找元素效率低下

单链表常见结构:


2、文件组织方式


3、linkList.h单链表函数声明文件

#ifndef _YE_LELE_01
#define _YE_LELE_01
typedef int ElemType;
typedef int Status;

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

//初始化一个线性的链表结构
Status Init_L(LinkList &L);

//销毁链表
Status Destory_L(LinkList &L);

//重置链表
Status ClearList_L(LinkList &L);

//判断链表中是否为空
Status Is_Emtpy(LinkList L);

//获取链表中元素的个数
Status L_Length(LinkList L);

//从链表中获取一个元素的值返回给元素e 
Status GetElem_L(LinkList L, int i, ElemType &e);

//找到链表中的元素与指定元素匹配的位置
Status LocalElem_L(LinkList L, int e, ElemType(*compare)(ElemType, ElemType));

//插入一个元素到链表中指定的位置
Status ListInsert_L(LinkList &L, int i, ElemType e);

//从链表中删除指定的元素,并且将该元素的值返回给e
Status ListDelete_L(LinkList &L, int i, ElemType &e);

//遍历链表中的元素
Status ListTraverse_L(LinkList L);

//逆位序创建线性链表,创建的链表长度为n
void CreateList_F(LinkList &L, int n);

//顺序创建线性链表,创建的链表长度为n
void CreateList_B(LinkList &L, int n);

//对链表中的元素进行排序
void InserSortList(LinkList &L);

//合并两个链表
void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc);

#endif

4、linkList.cpp单链表函数实现文件

#include<stdio.h>
#include<stdlib.h>
//排除VS2015当中的警告错误
#pragma warning (disable:4996)
#define ERROR -2
#define OVERFLOW -3
#define OK 1
#define TRUE 1
#define FALSE 0
typedef int ElemType;
typedef int Status;
//定义单链表的节点
typedef struct LNode
{
	ElemType data;  //数据元素
	struct LNode *next;//指向下一个节点的指针
}LNode, *LinkList;  //LinkList才作为表的节点,LNode表示节点的别名(表示节点类型)

Status Init_L(LinkList &L)
{
	L = (LinkList)malloc(sizeof(LNode));
	if (!L)
	{
		exit(OVERFLOW);//如果节点申请内存失败,程序溢出
	}
	L->next = NULL;//创建一个头结点
	return OK;
}

Status Destory_L(LinkList &L)
{
	if (!L)
	{
		exit(ERROR);//链表不存在的时候返回错误
	}
	free(L);//直接释放链表的头指针
	return OK;
}

Status ClearList_L(LinkList &L)
{
	if (!L)
	{
		exit(ERROR);//链表不存在的时候返回错误
	}
	free(L->next);//将链表的头结点以后的内容全部清除
	return OK;
}

Status Is_Emtpy(LinkList L)
{
	if (!L)
	{
		exit(ERROR);//链表不存在的时候返回错误
	}
	if (L->next == NULL)//如果链表为空,返回真
	{
		return TRUE;
	}
	else//否则返回假
	{
		return FALSE;
	}
}

Status L_Length(LinkList L)
{
	LinkList p = L->next;
	int count = 0;
	if (!L)
	{
		exit(ERROR);//链表不存在的时候返回错误
	}
	while (p)
	{
		count++;
		p = p->next;//此处不能写p++,p只是指向当前节点,不一定指向连续空间;
	}
	return count;
}

Status GetElem_L(LinkList L, int i, ElemType &e)
{
	int j = 1;
	LinkList p = L->next;
	if (!L)
	{
		exit(ERROR);//链表不存在的时候返回错误
	}
	while (p&&j<i)
	{
		p = p->next;//p指针后移
		j++;
	}
	if (!p || j>i)//表示该元素不存在
	{
		return ERROR;
	}
	e = p->data;
	return OK;
}

Status ListInsert_L(LinkList &L, int i, ElemType e)
{
	int j = 1;
	LinkList p = L;//p指向链表的头结点
	LinkList s;//新定义一个表节点
	while (p&&j <= i - 1)//寻找第i-1个节点,也就是需要插入位置的前一个节点
	{
		p = p->next;
		j++;
	}
	if (!p)//插入位置非法
	{
		return ERROR;
	}
	s = (LinkList)malloc(sizeof(LNode));//每一个节点都作为一个指针指向的对象
	s->data = e;
	s->next = p->next;
	p->next = s;
	return OK;
}

Status ListTraverse_L(LinkList L)
{
	int j = 1;
	LinkList p = L->next;
	while (p)
	{
		printf("%d\n", p->data);
		p = p->next;
	}
	return OK;
}

Status ListDelete_L(LinkList &L, int i, ElemType &e)
{
	int j = 1;
	LinkList p = L, q;
	while (p&&j <= i - 1)//寻找第i-1个节点,也就是需要删除位置的前一个节点
	{
		p = p->next;
		j++;
	}
	if (!p->next)//删除的位置不合理
	{
		return ERROR;
	}
	q = p->next;
	e = q->data;//将删除的数据放入到e中
	p->next = q->next;
	free(q);//释放内存
	return OK;
}
//在链表头插入节点
void CreateList_F(LinkList &L, int n)
{
	int i;
	LinkList p;
	for (i = n; i >0; i--)
	{
		p = (LinkList)malloc(sizeof(LNode));
		printf("输入链表中的节点数据:");
		scanf("%d", &p->data);
		p->next = L->next;
		L->next = p;
	}
}
//在链表尾部插入节点
void CreateList_B(LinkList &L, int n)
{
	int i;
	LinkList p = L;
	while (p->next != NULL)//找到链表末尾
	{
		p = p->next;
	}
	for (i = n; i >0; i--)
	{
		LinkList p1 = (LinkList)malloc(sizeof(LNode));//新申请一个节点
		p1->next = NULL;//给新节点的链接节点置空
		printf("输入链表中的节点数据:");
		scanf("%d", &p1->data);//为新节点赋值数据
		p->next = p1;//链接节点
		p = p->next;//节点后移
	}
}


//L 里面的data没有存储元素
void InserSortList(LinkList &L)
{
	LNode *p1, *p2, *temp, *prep1, *prep2;
	//在只有一个头结点+一个元素节点的情况下,无需排序
	if (L->next->next == NULL)
	{
		exit(0);
	}
	for (p1 = L->next->next, prep1 = L->next; p1 != NULL; p1 = p1->next, prep1 = prep1->next)
	{
		temp = p1;    /*保存待插入节点*/
		for (p2 = L->next, prep2 = L; p2 != p1; p2 = p2->next, prep2 = prep2->next)
		{
			if (p2->data > p1->data)
			{
				p1 = p1->next;
				prep1->next = temp->next;    /*删除待插入节点*/
				prep2->next = temp;              /*将其插入对应位置*/
			}
		}
		temp->next = p2;
	}
}


void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc)
{
	LNode *pa, *pb, *pc;
	pa = La->next; pb = Lb->next;
	Lc = pc = La;
	while (pa&&pb)
	{
		if (pa->data<pb->data)
		{
			pc->next = pa; pc = pa; pa = pa->next;
		}
		else
		{
			pc->next = pb; pc = pb; pb = pb->next;
		}
	}
	pc->next = pa ? pa : pb;
	free(Lb);
}

5、主函数调用文件main.cpp

#include<stdio.h>
#include<stdlib.h>
#include"linkList.h"

ElemType e = 0;
LinkList L, La, Lb, Lc;

//通过插入元素创建链表
void init()
{
	printf("***********线性表的链式操作实验***********\n");
	printf("线性表的初始化插入操作\n");
	Init_L(L);//调用初始化过程
	Init_L(La);
	Init_L(Lb);
	Init_L(Lc);
	printf("初始化完成\n");
}

void test1()
{
	ListInsert_L(L, 1, 2);//插入元素2
	ListInsert_L(L, 1, 3);//插入元素3
	ListInsert_L(L, 2, 8);//插入元素8
	ListInsert_L(L, 3, 6);//插入元素6
	ListInsert_L(L, 4, -1);//插入元素-1
	ListInsert_L(L, 5, 7);//插入元素7
	ListTraverse_L(L);
}
//获取链表元素
void test2()
{
	printf("线性表的获取元素操作\n");
	GetElem_L(L, 2, e);
	printf("%d\n", e);
}
//判断链表中是否为空
void test3()
{
	printf("线性表判断链表中是否为空\n");
	e = Is_Emtpy(L);
	if (e)
	{
		printf("空\n");
	}
	else
	{
		printf("非空\n");
	}
}
//链表中元素的个数
void test4()
{
	printf("链表中元素的个数\n");
	printf("%d\n", L_Length(L));
}

//获取一个元素
void test5()
{
	printf("链表中获取一个元素的值返回给元素e\n");
	GetElem_L(L, 5, e);
	printf("%d\n", e);
}

//链表中删除指定的元素
void test6()
{
	printf("链表中删除指定的元素\n");
	ListDelete_L(L, 3, e);
	ListTraverse_L(L);
}
//逆位序创建线性链表
void test7()
{
	printf("逆位序创建线性链表\n");
	CreateList_F(La, 3);
	ListTraverse_L(La);
	CreateList_F(Lb, 3);
	ListTraverse_L(Lb);
}

//链表合并
void test8()
{
	MergeList_L(La, Lb, Lc);
	ListTraverse_L(Lc);
}

void test9()
{
	printf("顺序创建线性链表\n");
	CreateList_B(La, 3);
	ListTraverse_L(La);
	CreateList_B(Lb, 3);
	ListTraverse_L(Lb);
}

int main()
{
	init();
	//test7();
	test9();
	test8();
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值