数据结构与算法------链表


  一、单链表

   (1)用代码定义单链表

// ********************************* < 定义单链表 > *********************************

	typedef struct LNode     // 定义单链表结点类型
	{
		int data;            // 每个结点存放一个数据元素 
		struct LNode *next;  // 指针指向下一个结点
	}LNode, *LinkList;


	// 要定义一个单链表时,只需声明一个头指针 “L”,指向单链表的第一个结点

	LNode *L;   // 声明一个指向单链表 "头节点" 的指针(强调这是一个结点!!!)

	// 或者(两种形式等价)
	LinkList L;  // 声明一个指向单链表 "头节点" 的指针(强调这是一个单链表)
	

   (2)创建单链表

// ********************************* < 创建单链表 > *********************************
	
	// 创建“不带头节点”的单链表!!!!!!!!!!!!!!!!!!!(操作不方便)

	LinkList L;   // 声明一个指向单链表的指针

	bool InitList(LinkList &L)
	{
		
		L = Null;  // 空表,没有任何结点

		return true;
	}

	// 初始化一个空表
	InitList(L);



	// 创建“带头节点”的单链表!!!!!!!!!!!!!!!!!!!(操作方便)

	LinkList L;   // 声明一个指向单链表的指针

	bool InitList(LinkList &L)
	{

		L = (LNode *)malloc(sizeof(LNode));  // 分配一个头节点

		if (L == NULL)   // 若内存不足,则创建失败(增加代码健壮性)
		{
			return false;
		}

		L->next = NULL;  // 头节点之后暂时还没有节点(防止脏数据)

		return true;
	}

	// 初始化一个空表
	InitList(L);

   (3)单链表的插入

// ********************************* < 单链表的插入 > *********************************

	// 单链表“按位序插入”(带头节点)!!!!!!!!!!!!!!!!!!!
	bool ListInsert(LinkList &L, int i, int e)     // 注意链表前的(&)引用符号!!!
	{
		if (i < 1) 
		{
			return false;
		}

		LNode *p;      // 指针 p 指向当前扫描到的结点
		int j = 0;     // 当前 p 指向的是第几个结点
		p = L;         // L指向头节点,头节点是第 0  个结点(不存数据)

		while (p != NULL && j < i - 1)    // 循环找到第 i-1 个结点
		{
			p = p->next;
			j++;
		}

		if (p == NULL)  // i 值不合法时
		{
			return false;
		}

		LNode *s = (LNode *)malloc(sizeof(LNode));

		s->data = e;
		s->next = p->next;
		p->next = s;    // 将结点 s 连到 p 之后
		return true;    // 插入成功

	}


	// 单链表“按位序插入”(不带头节点)!!!!!!!!!!!!!!!!!!!
	bool ListInsert(LinkList &L, int i, int e)     // 注意链表前的(&)引用符号!!!
	{
		if (i < 1)
		{
			return false;
		}

		if (i == 1)    // 插入第 1 个结点的操作与其他结点操作不同!!!!!!!!!!!!!!!!!!!!!!
		{
			LNode *s = (LNode *)malloc(sizeof(LNode));
			s->data = e;  // 插入数据 e
			s->next = L;
			L = s;        // 头指针指向新节点
			return true;
		}


		LNode *p;      // 指针 p 指向当前扫描到的结点
		int j = 1;     // 当前 p 指向的是第几个结点 !!!!!!!!!!!!!!!!!!!!!!!!  与带头结点的不同之处 !!!!!!!!!!!!!!!!!!!!!!
		p = L;         // L指向头节点,头节点是第 1  个结点(不存数据)

		while (p != NULL && j < i - 1)    // 循环找到第 i-1 个结点
		{
			p = p->next;
			j++;
		}

		if (p == NULL)  // i 值不合法时
		{
			return false;
		}

		LNode *s = (LNode *)malloc(sizeof(LNode));

		s->data = e;
		s->next = p->next;
		p->next = s;    // 将结点 s 连到 p 之后
		return true;

	}




	// 指定结点的后插操作 !!!!!!!!!!!!!!!!!!!
	bool InsertNextNode(LinkList *p, int e)
	{
		if (p == NULL)     // 若内存分配失败
		{
			return false;
		}
		LNode *s = (LNode *)malloc(sizeof(LNode));
		if (s == NULL)     // 若内存分配失败
		{
			return false;
		}


		s->data = e;
		s->next = p->next;
		p = s;

		return true;
	}



	// 指定结点的前插操作 !!!!!!!!!!!!!!!!!!!
	bool InsertPriorNode(LinkList *p, int e)
	{
		if (p == NULL)     // 若内存分配失败
		{
			return false;
		}
		LNode *s = (LNode *)malloc(sizeof(LNode));
		if (s == NULL)     // 若内存分配失败
		{
			return false;
		}

		// 即创建一个 结点s 来代替 结点p,结点p 作为前插结点!!!!!!
		s->next = p->next;
		p->next = s;
		s->data = p->data;  // p中元素复制给 s
		p->data = e;        // p中元素覆盖为 e

		return true;
	}

   (4)单链表的删除

	// ********************************* < 单链表的删除 > *********************************

	// 单链表“按位序删除”(带头节点)!!!!!!!!!!!!!!!!!!!
	bool ListDelete(LinkList &L, int i, int &e) 
	{
		if (i < 1)
		{
			return false;
		}

		LNode *p;     // 指针 p 指向当前扫描到的结点
		int j = 0;	  // 当前 p 指向的是第几个结点
		p = L;        // L 指向头节点,头节点为第0个结点(不存数据)

		while (p != NULL && j < i - 1)  // 循环找到第 i-1 个结点
		{
			p = p->next;
			j++;
		}

		if (p == NULL)   // i值不合法
		{
			return false;
		}

		if (p->next == NULL)  // 第 i-1 个结点后已无结点
		{
			return false;
		}

		LNode *q = p->next;   // 令 q 指向需要被删除结点
		e = q -> data;        // 用 e 存放返回元素的值
		p->next = q->next;    // p 指向 q 之后结点,即断开 q 结点

		free(q);     // 释放 q 结点,删除成功

		return true;
	}


	// 指定结点的删除操作 !!!!!!!!!!!!!!!!!!!
	bool DeleteNode(LNode *p) 
	{
		if (p == NULL)
		{
			return false;
		}
		
		LNode *q = p->next;        // 令 q 指向 p 的后继节点
		p->data = p->next->data;   // 和后继节点交换数据域
		p->next = q->next;         // p 指向 q 的后继节点,即断开 q

		free(q);   // 释放结点 q,即删除成功
		
		return true;
	}

   (5)单链表的查找及长度计算

// ********************************* < 单链表的查找 > *********************************

	// 按值查找操作 !!!!!!!!!!!!!!!!!!!
	LNode *FindElem(LinkList L, int e) 
	{
		LNode *p = L->next;  // p 指向第一个结点

		while (p != NULL && p->data != e) // 从第一个结点开始查找数据为 e 的结点
		{
			p = p->next;
		}

		return p;  // 找到后返回该结点指针,否则返回 NULL
	}

	// 求链表长度 !!!!!!!!!!!!!!!!!!!
	int GetLength(LinkList L)
	{
		LNode *p = ;  // p 指向头节点!!!!!!
		int len = 0;  // 统计表长

		while (p != NULL) // 从第一个结点开始查找数据为 e 的结点
		{
			p = p->next;
			++len;
		}

		return len;  // 找到后返回该结点指针,否则返回 NULL
	}

   (6)“尾插法” 建立单链表

// ********************************* < 尾插法建立单链表 > *********************************

	LinkList  List_TailInsert(LinkList &L)     // 正向建立链表
	{
		L = (LinkList)malloc(sizeof(LNode)); // 建立头节点

		LNode *s;    // s 指向待插入部分
		LNode *r = L;    // r 为表尾指针

		int x;   // 待插入元素
		scanf("%d", &x);

		while (x != 9999)    // 假定输入 9999 表示插入结束
		{
			// 在 r 之后插入元素 x
			s = (LinkList)malloc(sizeof(LNode));
			s->data = x;
			r->next = s;

			r = s;     // r 始终指向表尾

			scanf("%d", &x);
		}

		r->next = NULL;   // 尾结点指针置空

		return L;   // 返回建立好的链表的头结点
	}

   (7)“头插法” 建立单链表(链表逆置)

// ********************************* < 头插法建立单链表(链表逆置) > *********************************
// 将需要逆置的链表顺序遍历,用头插法插入到另一个链表中,即实现了链表逆置!!!!!!!!!!!

	LinkList  List_HeadInsert(LinkList &L)     // 正向建立链表
	{
		L = (LinkList)malloc(sizeof(LNode)); // 建立头节点
		L->next = NULL;    // 初始为空链表 !!!!!!!!很重要!!!!!!!!!

		LNode *s;    // s 指向待插入部分

		int x;   // 待插入元素
		scanf("%d", &x);

		while (x != 9999)    // 假定输入 9999 表示插入结束
		{
			// 在 r 之后插入元素 x
			s = (LinkList)malloc(sizeof(LNode));
			s->data = x;
			s->next = L->next;
			L->next = s;        // 插入新结点,L 为头指针

			scanf("%d", &x);
		}


		return L;   // 返回建立好的链表的头结点
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值