重拾数据结构(二)— 线性表(顺序 单链表)增删改查,对代码的理解

直接附代码慢慢看;
编程工具: vs2015,主要语言c++。
数据结构: 大话数据结构

#include <iostream>
#include <time.h>
using namespace std;

#pragma region  状态申明
#define ok 1
#define error 0
#define MAXSIZE 20

typedef int Status; //函数的返回状态(int),实际不一定
typedef int ElemType;// 同理

typedef struct Node
{
	ElemType data;
	struct Node *next; //指向自己的一个指针
}Node;
typedef struct Node *LinkList; //单向链表
#pragma endregion

#pragma region 初始化函数
Status  ListInit(LinkList *L)              //初始化
//需要把目标初始化,故需要传指针
{
	try
	{
		*L = new Node;
		(*L)->next = NULL;
	}
	catch (const std::exception&)
	{
		return error;
	}
}


Status ListOutput(LinkList L) //打印输出
{
	LinkList p = L->next;//第一个节点
	while (p)
	{
		cout << p->data << "   ";
		p = p->next;
	}
	cout << endl;
	return ok;
}

Status ListLength(LinkList L) //返回长度
{
	int i=0;
	while (L->next)
	{ 
		i++;
		L = L->next;
	}
	return i;
}
#pragma endregion


#pragma region 增删改查

Status GetElem(LinkList L, int i, ElemType *e)   //查看元素
												 //只是查看值,L不需要改变,不用传地址
{
	int j = 1;
	LinkList p = L->next;//第一个节点
	while (p && j<i)   //判断位置,链表是否为空(未分配空间)
	{
		p = p->next;
		++j;
	}
	if (!p || j > i) //为空或者第i个元素不存在
		return error;
	*e = p->data;
	return ok;
}

Status ListInsert(LinkList *L, int i, ElemType e)  //插入元素
//需要传递的L一起改变,传递地址
{
	int j = 1; LinkList s, p = *L;
	//查找的功能部分
	while (p && j < i)     /* 寻找第i个结点 */
	{
		p = p->next;
		++j;
	}
	if (!p || j > i)
		return error;   /* 第i个元素不存在 */
						// 插入 代替的部分
	//s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */
	s = new Node;
	s->data = e;
	s->next = p->next;      /* 将p的后继结点赋值给s的后继  */
	p->next = s;          /* 将s赋值给p的后继 */
	return ok;
}

Status ListDelete(LinkList *L,int i, ElemType *e)  //删除元素
{//返回删除的值
	int j = 1; LinkList s, p = *L;
	//查找的功能部分
	while (p && j < i)     /* 寻找第i个结点 */
	{
		p = p->next; //第一个数据
		++j;
	}
	if (!p || j > i)
		return error;   /* 第i个元素不存在 */
	s = p->next;  // p->next  这边才是第i的数据
	p->next = s->next;
	*e = s->data;
	delete s;
	return ok;
}


Status ClearList(LinkList *L)
{
	LinkList s, q;//s为释放的点
	s = (*L)->next;           /*  p指向第一个结点 */
	while (s)                /*  没到表尾 */
	{
		q = s->next;
		free(s);  //指向下一个
		s = q;
	}
	(*L)->next = NULL;        /* 头结点指针域为空 */
	return ok;
}
#pragma endregion


#pragma region 头插和尾插
void CreateListHead(LinkList *L, int n)
{
	LinkList p;
	int i;
	srand(time(0));                         /* 初始化随机数种子 */
	//*L = (LinkList)malloc(sizeof(Node));
	*L = new Node;
	(*L)->next = NULL;                      /*  先建立一个带头结点的单链表 */
	for (i = 0; i<n; i++)
	{
		//p = (LinkList)malloc(sizeof(Node)); /*  生成新结点 */
		p = new Node;
		p->data = rand() % 100 + 1;             /*  随机生成100以内的数字 */
		p->next = (*L)->next;         //把前一个头结点数据给p的下一个节点
		                             //实现循环,一直添加在p的后面
		(*L)->next = p;				//永远是头结点		/*  插入到表头 */
	}
}

void CreateListTail(LinkList *L, int n)
{
	LinkList p, r;
	int i;
	srand(time(0));                      /* 初始化随机数种子 */
	//*L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */
	*L = new Node;
	r = *L;                                /* r为指向尾部的结点 */
	for (i = 0; i<n; i++)
	{
		//p = (Node *)malloc(sizeof(Node)); /*  生成新结点 */
		p = new Node;
		p->data = rand() % 100 + 1;           /*  随机生成100以内的数字 */
		r->next = p;                        /* 将表尾终端结点的指针指向新结点 */
		r = p;                            /* 将当前的新结点定义为表尾终端结点 */
	   //这段也是想了好久才想通, 
	   /*
	     我的理解是 r是指向尾端的节点, 
		 当r->next=p时,由于增加了一个元素导致r不在 尾部
		   r->next=p是为L服务的
		 这时候r=p,就是把尾部地址给它,r->next就可以继续循环
	   */
	}
	r->next = NULL;                       /* 表示当前链表结束 */
}
#pragma endregion

//主函数 ,都有返回值,if 不判断成功与否,可以不用返回值
// 头指针不附带数据,
int main()
{
	LinkList L; ElemType e; //链表
    
	ListInit(&L);
	cout << "初始化后链表的长度"<< ListLength(L)<<endl;
	
	for (int i = 1; i <= 5; i++)
		ListInsert(&L, 1, i);
	cout << "插入元素之后";
	ListOutput(L);
	cout << "测试头指针是否有数据" << L->data << endl;

    ListDelete(&L, 3, &e);
	cout << "删除的元素是" << e << endl;

	ClearList(&L);
	cout << "清空数据之后的长度为" <<ListLength(L)<< endl;
	CreateListHead(&L,6);
	cout << "头插法的数据为";
	ListOutput(L);

	ClearList(&L);
	cout << "清空数据之后的长度为" << ListLength(L) << endl;
	CreateListTail(&L, 5);
	cout << "尾插法的数据为";
	ListOutput(L);


	getchar();
	return 0;
}

循环链表

typedef struct DulNode
{
   ElemType data;//存储数据的
   struct DulNode *prior;//指向前驱指针
   struct DulNode *next;//指向后继的指针
}DulNode,*DuLinkList;


//删除 
p->prior->next=p->next;
p->next->prior=p->prior;

删除

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值