数据结构——线性表

一、单项链表

1.自动扩容(增)

1.1扩容函数 (顺序表的尾添加)

// 扩容函数 
void  ZengJia ( struct  Dongshuzu *  pShuzu ,  int  iShuju ) 
{ 
	if  ( pShuzu -> iRongliang  ==  pShuzu -> iShuliang )  // 当容量==数量的时候需要扩容 
	{ 
		// 容量变大 
		pShuzu -> iRongliang  +=  10 ; 
		// 申请一个新空间来装原有数据 
		int *  pTemp  =  ( int * ) malloc ( sizeof ( int )  *  pShuzu -> iRongliang ) ; 
		// 将源数据复制进新空间 
		for  ( unsigned  int  i  =  0 ;  i  <  pShuzu -> iRongliang ;  i ++ ) 
		{ 
			pTemp [ i ]  =  pShuzu -> pShuzutou [ i ] ; 
		} 
		// 将源空间释放 
		free ( pShuzu -> pShuzutou ) ; 
		// 将数组头指针指向新空间 
		pShuzu -> pShuzutou  =  pTemp ; 

	} 
	//将数据装进去
	pShuzu->pShuzutou[pShuzu->iShuliang] = iShuju;  // 数字头[数量]数量的初始值为0
	// 与存储数据量++
	pShuzu->iShuliang++;

}

1.2 链表的释放


// 链式链表的释放
void FreeList(struct Node* pHead)
// 链表的释放只需要传一级的指针,是需要释放链表指向的地址,如果想要在释放后把pHead的的值赋值为NULL,就需要二级指针
{
	while (pHead != NULL)
	{
		// 如果在这里直接free(pHead)释放,则下一步的pHead就没有了,下一步就是错误的
		struct Node* pt = pHead; // 用一个临时变量储存pHead
		pHead = pHead->pNext;
		free(pt); //释放临时变量
	}
}

1.3 完整 程序

# include<stdio.h>
# include<malloc.h>

struct Dongshuzu
{
	int* pShuzutou;  // 首地址
	unsigned int iRongliang;  // 容量
	unsigned int iShuliang;  //已存储的数量
};
// 初始化函数
void ChuShiHua(struct Dongshuzu* pShuzu);

// 扩容函数
void ZengJia(struct Dongshuzu* pShuzu, int iShuju);

// 将数据输出
void ShuChu(struct Dongshuzu* stshuzu);


int main(void)
{
	struct Dongshuzu stshuzu;
	ChuShiHua(&stshuzu);

	ZengJia(&stshuzu, 1);
	ZengJia(&stshuzu, 2);
	ZengJia(&stshuzu, 3);
	ZengJia(&stshuzu, 4);
	ZengJia(&stshuzu, 5);
	ZengJia(&stshuzu, 6);

	ShuChu(&stshuzu);

	free(stshuzu.pShuzutou);
	return 0;
}
// 初始化函数
void ChuShiHua(struct Dongshuzu* pShuzu)
{
	pShuzu->iRongliang = 5;  //设置初始容量
	pShuzu->pShuzutou = malloc(sizeof(int) * pShuzu->iRongliang); //为设置的初始容量申请空间
	pShuzu->iShuliang = 0;  // 初始时已存储数量为0
}
// 扩容函数
void ZengJia(struct Dongshuzu* pShuzu, int iShuju)
{
	if (pShuzu->iRongliang == pShuzu->iShuliang) // 当容量==数量的时候需要扩容
	{
		// 容量变大
		pShuzu->iRongliang += 10;
		// 申请空间
		int* pTemp = (int*)malloc(sizeof(int) * pShuzu->iRongliang);
		// 将源数据复制进新空间
		for (unsigned int i = 0; i < pShuzu->iRongliang; i++)
		{
			pTemp[i] = pShuzu->pShuzutou[i];
		}
		// 将源空间释放 
		free ( pShuzu -> pShuzutou ) ; 
		// 将数组头指针指向新空间 
		pShuzu -> pShuzutou  =  pTemp ; 

	}
	//将数据装进去
	pShuzu->pShuzutou[pShuzu->iShuliang] = iShuju;  
	// 数组的数量是比数组的下标值大1,添加时在结尾添加,所以新添加的数据的数组下标值=数据的数量值
	pShuzu->iShuliang++;// 与存储数据量++

}

// 将数据输出
void ShuChu(struct Dongshuzu* stshuzu)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == stshuzu)
	{
		printf("参数错误");
		return;
	}
	printf("容量:%u,数量:%u\n", stshuzu->iRongliang, stshuzu->iShuliang);
	printf("数据:");
	for (unsigned int i = 0; i < stshuzu->iShuliang; i++)
	{
		printf("%d ", stshuzu->pShuzutou[i]);
	}
}

1.3 链表的头添加

// 头添加
void AddToHead(struct Node** pHead, struct Node** pEnd, int iData)
{
	// 创建结点,用新创建的结点来装形参
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	// 节点成员赋值
	if (pTemp != NULL)
	{
		// 新结点装上形参后连接
		pTemp->iData = iData;
		pTemp->pNext = NULL;  // 尾结点赋值成空很重要
		// 新结点装上形参后连接合适的位置
		if (NULL == pTemp)// 如果为空新加节点既是头也是尾
		{
			*pEnd = pTemp;
			// *pHead = pTemp;
		}
		else //如果不为空,新的结点的下一个结点为原来的头指针
		{
			pTemp->pNext = *pHead;
			// *pHead = pTemp;
		}
		// 把新添加到头部的结点从新设置为头结点
		*pHead = pTemp;
	}

}

1.4 链表的尾添加

// 尾添加
void AddToEnd(struct Node** pHead, struct Node** pEnd, int iData)
//该函数的参数是指针,而该函数要修改这个指针的指向,所以参数为二级指针。
{
	// 创建节点
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	if (pTemp != NULL)
	{
		// 节点成员赋值,每一个成员都要赋值
		pTemp->iData = iData;
		// 尤其是pTemp->pNext结点一定要赋值为空,会影响到后面的链表的操作
		pTemp->pNext = NULL;

		//连上去
		if (*pHead == NULL)  //如果链表为空
		{
			*pHead = pTemp;
			//*pEnd = pTemp;
			//空量表头和尾都是空,所以头指针和尾指针是相同的。
		}
		else  // 如果链表原来不为空,则新的结点连到尾部
		{
			(*pEnd)->pNext = pTemp; //新节点练到尾部
			//*pEnd = pTemp;  // 尾指针指向新来的尾部添加节点
		}
		*pEnd = pTemp; // 两步判断里都要使尾部指针指向,新添加的尾节点可以直接放到判断外部  ,节省一步。
	}

}

// 没有尾指针的尾添加
void AddToEndNoEnd(struct Node** pHead, int iData)
{
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	if (pTemp != NULL)
	{
		// 节点成员赋值,每一个成员都要赋值
		pTemp->iData = iData;
		// 尤其是pTemp->pNext结点一定要赋值为空,会影响到后面的链表的操作
		pTemp->pNext = NULL;
		// 连接
		if (*pHead == NULL) // 如果之前指针为空,则添加的就是头指针
		{
			*pHead = pTemp;
		}
		else  // 如果之前指针不为空,添加的就要连到后面,通过循环找到尾
		{
			struct Node* pt = *pHead;  //定义一个临时的中间变量指向头
			while (pt->pNext != NULL) //找尾,循环到空的时候是尾
			{
				pt = pt->pNext;  //因为要对pt进行从新赋值,所以要使用一个中间变量,否则记录的头指针就没了
			}
			pt->pNext = pTemp;  //当pt->pNext等于NULL时,这是pt为最后一项。
		}
	}
	
}

1.5 链表的中间添加

// 中间添加
void AddToMiddle(struct Node** pHead, struct Node** pEnd, int Index, int iData)
{
	// 创建结点,用新创建的结点来装形参
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	// 节点成员赋值
	if (pTemp != NULL)
	{
		// 新结点装上形参后连接
		pTemp->iData = iData; 
		pTemp->pNext = NULL;  // 尾结点赋值成空很重要
		// 根据下标查找结点
		if (Index == 0) // 如果下标=0,添加到头部
		{
			AddToHead(pHead, pEnd, iData);
		}
		else // 根据下标查找结点
		{
			struct Node* pTemp = FindByIndex(*pHead, Index);
			{
				if (pTemp != NULL)
				{
					// 申请临时空间
					struct Node* pT = (struct Node*)malloc(sizeof(struct Node));
					if (pT != NULL)
					{
						// 节点赋值
						pT->iData = iData;
						pT->pNext = NULL;
						// 连接上,先连后断
						pT->pNext = pTemp->pNext;
						pTemp->pNext = pT;
					}
				}
			}
		}
	}
}

2.删除元素

删除元素的平均复杂度:O(n)

2.1 顺序链表的删除


// 删除尾
// 数量减一
void ShanChuWei(struct DongShuZu* pShuZu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	pShuZu->iShuLiang--;
}

// 删除全部
// 数量设置为0
void ShanChuQuanBu(struct DongShuZu* pShuZu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	pShuZu->iShuLiang = 0;
}

// 删除全部并清除空间
// 数量、容量都设置为零;释放头指针地址;头指针设置为NULL
void Qingkong(struct DongShuZu* pShuZu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	pShuZu->iShuLiang = 0;
	pShuZu->iRongLiang = 0;
	free(pShuZu->pShuZuTou);
	pShuZu->pShuZuTou = NULL;
}

// 删除中间元素
void ShanChuZhongJian(struct DongShuZu* pShuZu, int iXiaBiao)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	// 后面往前移
	for (unsigned int i = iXiaBiao - 1; i < pShuZu->iShuLiang; i++)
	{
		pShuZu->pShuZuTou[i] = pShuZu->pShuZuTou[i + 1];
	}
	pShuZu->iShuLiang--;
}

// 将数据输出
void ShuChu(struct DongShuZu* pShuZu)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	printf("容量:%u,数量:%u\n", pShuZu->iRongLiang, pShuZu->iShuLiang);
	printf("数据:");
	for (unsigned int i = 0; i < pShuZu->iShuLiang; i++)
	{
		printf("%d ", pShuZu->pShuZuTou[i]);
	}
	printf("\n");
}

# include<stdio.h>

// 定义结构体
struct DongShuZu
{
	int* pShuZuTou;
	unsigned int iRongLiang;
	unsigned int iShuLiang;
};
// 结构体初始化
void ChuShiHua(struct DongShuZu* pShuZu);

// 自动扩容
void ZengJia(struct DongShuZu* pShuZu, int iShuJu);

// 删除尾
// 数量减一
void ShanChuWei(struct DongShuZu* pShuZu);

// 删除全部
// 数量设置为0
void ShanChuQuanBu(struct DongShuZu* pShuZu);

// 删除全部并清除空间
// 数量、容量都设置为零;释放头指针地址;头指针设置为NULL
void Qingkong(struct DongShuZu* pShuZu);

// 删除中间元素
void ShanChuZhongJian(struct DongShuZu* pShuZu, int iXiaBiao);

// 将数据输出
void ShuChu(struct DongShuZu* pShuZu);

int main(void)
{
	struct DongShuZu stShuZu;
	ChuShiHua(&stShuZu);

	ZengJia(&stShuZu, 1);
	ZengJia(&stShuZu, 2);
	ZengJia(&stShuZu, 3);
	ZengJia(&stShuZu, 4);
	ZengJia(&stShuZu, 5);
	ZengJia(&stShuZu, 6);
	ZengJia(&stShuZu, 7);
	ZengJia(&stShuZu, 8);
	ZengJia(&stShuZu, 9);
	ShuChu(&stShuZu);

	ShanChuWei(&stShuZu);
	ShuChu(&stShuZu);

	ShanChuZhongJian(&stShuZu, 3);
	ShuChu(&stShuZu);

	ShanChuQuanBu(&stShuZu);
	ShuChu(&stShuZu);

	Qingkong(&stShuZu);
	ShuChu(&stShuZu);

}

// 结构体初始化
void ChuShiHua(struct DongShuZu* pShuZu)
{
	pShuZu->iRongLiang = 5;
	pShuZu->pShuZuTou = malloc(sizeof(int) * pShuZu->iRongLiang);
	pShuZu->iShuLiang = 0;
}

// 自动扩容
void ZengJia(struct DongShuZu* pShuZu, int iShuJu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	if (pShuZu->iRongLiang == pShuZu->iShuLiang)
	{
		pShuZu->iRongLiang += 5;
		int* pTemp = malloc(sizeof(int) * pShuZu->iRongLiang);
		for (unsigned int i = 0; i < pShuZu->iRongLiang; i++)
		{
			pTemp[i] = pShuZu->pShuZuTou[i];
		}
		free(pShuZu->pShuZuTou);
		pShuZu->pShuZuTou = pTemp;
	}
	pShuZu->pShuZuTou[pShuZu->iShuLiang] = iShuJu;
	pShuZu->iShuLiang++;
}

// 删除尾
void ShanChuWei(struct DongShuZu* pShuZu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	pShuZu->iShuLiang--;
}

// 删除全部
void ShanChuQuanBu(struct DongShuZu* pShuZu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	pShuZu->iShuLiang = 0;
}

// 删除全部并清除空间
void Qingkong(struct DongShuZu* pShuZu)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	pShuZu->iShuLiang = 0;
	pShuZu->iRongLiang = 0;
	free(pShuZu->pShuZuTou);
	pShuZu->pShuZuTou = NULL;
}

// 删除中间元素
void ShanChuZhongJian(struct DongShuZu* pShuZu, int iXiaBiao)
{
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	// 后面往前移
	for (unsigned int i = iXiaBiao - 1; i < pShuZu->iShuLiang; i++)
	{
		pShuZu->pShuZuTou[i] = pShuZu->pShuZuTou[i + 1];
	}
	pShuZu->iShuLiang--;
}

// 将数据输出
void ShuChu(struct DongShuZu* pShuZu)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == pShuZu)
	{
		printf("参数错误");
		return;
	}
	printf("容量:%u,数量:%u\n", pShuZu->iRongLiang, pShuZu->iShuLiang);
	printf("数据:");
	for (unsigned int i = 0; i < pShuZu->iShuLiang; i++)
	{
		printf("%d ", pShuZu->pShuZuTou[i]);
	}
	printf("\n");
}

2.2 链式链表的删除

链式链表头删除
// 链式链表头删除
void DeleteHead(struct Node** pHead, struct Node** pEnd)
{
	if (*pHead == NULL)
	{
		return;
	}
	if ((*pHead)->pNext == NULL) //* pHea == *pEnd,此时只有一个结点,直接释放
	{
		free(*pHead);
	}
	else
	{
		struct Node* pT = *pHead;  //申请一个结点来装要删除的头结点
		*pHead = (*pHead)->pNext;  //头结点设置为她的下一个结点
		free(pT);  // 释放pT就相当于释放了原来的头结点,因为pT装的是原头结点
	}
}

链式链表尾删除
  1. 循环找到倒数第二个结点
  2. free最后一个结点
  3. 新的尾指针(即原来倒数第二个节点)的下一个结点设置为NULL
// 链式链表尾删除
void DeleteEnd(struct Node** pHead, struct Node** pEnd)
{
	if (*pHead == NULL)
	{
		return;
	}
	if ((*pHead)->pNext == NULL) //* pHea == *pEnd,此时只有一个结点,直接释放,但是要把下一个节点设置为NULL
	{
		free(*pHead);  //释放结点
		*pHead = NULL;
		*pEnd = NULL;
	}
	else
	{
		// 找到倒数第二个节点,目的是为了把最后一个节点的下一个设置为NULL
		struct Node* pT = *pHead;  //先定义一个中间变量来装要删除的头结点
		while (pT->pNext != *pEnd) // 当pT->pNext为*pEnd的时候,pT为倒数第二个节点
		{
			pT = pT->pNext;
		}
		// 找到之后
		free(*pEnd);  // 释放尾,而不是释放pT
		*pEnd = pT;  //再把尾结点设置为找到的倒数第二个结点
		(*pEnd)->pNext = NULL; // 最重要的是把新的pEnd->pNext设置为NULL

	}
}

链式链表中间删除
//  链式链表删除指定元素
void DeleteMiddle(struct Node** pHead, struct Node** pEnd, int iData)
{
	
	if (*pHead == NULL)
	{
		return;
	}
	// 判断头尾指针是否是指定数据,如果是,直接调用头删除,尾删除
	if ((*pHead)->iValue == iData)
	{
		DeleteHead(pHead, pEnd);
	}
	else if ((*pEnd)->iValue == iData)
	{
		DeleteEnd(pHead, pEnd);
	}
	else 
	{
		struct Node* pTemp = *pHead; //一定要新创建一个结点来装头结点来进行循环查找,否则头指针可能会被修改

		// 循环找数据结点
		while (pTemp->pNext != NULL)
		{
			if (pTemp->pNext->iValue == iData)
			{
				break;
			}
			pTemp = pTemp->pNext;
		}
		if (pTemp->pNext != NULL)
		{
			struct Node* pT = pTemp->pNext;  //记录要删除的结点,把pT这职位要删除结点的下一个结点
			pTemp->pNext = pT->pNext;  // 这样就把pT结点给抠出来了
			free(pT);
		}
		else
		{
			printf("节点中无数据:%d\n",iData);
		}
	}
}

3. 修改元素(插入、修改,替换)

3.1 顺序链表的插入

插入元素需要把插入点处的坐标,以及后面的元素向后移:
插入算法平均复杂的:O(n)

// 插入数据函数
void ChaRu(struct Dongshuzu* pShuzu, int iShuJu, unsigned int iXiaBiao)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == pShuzu)
	{
		printf("参数错误");
		return;
	}
	//当下表>容量的时候,把该元素添加到最后
	if (pShuzu->iRongliang == pShuzu->iShuliang) // 当容量==数量的时候需要扩容
	{
		// 容量变大
		pShuzu->iRongliang += 10;
		// 申请空间
		int* pTemp = (unsigned int*)malloc(sizeof(unsigned int) * pShuzu->iRongliang);

		// 将源数据复制进新空间
		for (unsigned int i = 0; i < pShuzu->iRongliang; i++)
		{
			pTemp[i] = pShuzu->pShuzutou[i];
		}
		// 将源空间释放
		free(pShuzu->pShuzutou);
		// 将数组头指针指向新空间
		pShuzu->pShuzutou = pTemp;

	}
	//当下标过大
	if (iXiaBiao > pShuzu->iShuliang)
	{
		iXiaBiao = pShuzu->pShuzutou[pShuzu->iShuliang];
	}
	//向后挪
	for (unsigned int i = pShuzu->iShuliang; i >= iXiaBiao; i--)
	{
		pShuzu->pShuzutou[i] = pShuzu->pShuzutou[i - 1];
	}
	// 数据插入到置定位是
	pShuzu->pShuzutou[iXiaBiao] = iShuJu;
	// 数据量++
	pShuzu->iShuliang++;

}

# include<stdio.h>
# include<string.h>
# include<malloc.h>

struct Dongshuzu
{
	int* pShuzutou;  // 首地址
	unsigned int iRongliang;  // 容量
	unsigned int iShuliang;  //已存储的数量
};
// 初始化函数
void ChuShiHua(struct Dongshuzu* pShuzu)
{
	pShuzu->iRongliang = 5;  //设置初始容量
	pShuzu->pShuzutou = malloc(sizeof(int) * pShuzu->iRongliang); //为设置的初始容量申请空间
	pShuzu->iShuliang = 0;  // 初始时已存储数量为0
}
// 扩容函数
void ZengJia(struct Dongshuzu* pShuzu, int iShuJu)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == pShuzu)
	{
		printf("参数错误");
		return;
	}

	if (pShuzu->iRongliang == pShuzu->iShuliang) // 当容量==数量的时候需要扩容
	{
		// 容量变大
		pShuzu->iRongliang += 10;
		// 申请空间
		int* pTemp = (unsigned int*)malloc(sizeof(unsigned int) * pShuzu->iRongliang);
		// 将源数据复制进新空间
		for (unsigned int i = 0; i < pShuzu->iRongliang; i++)
		{
			pTemp[i] = pShuzu->pShuzutou[i];
		}
		// 将源空间释放
		free ( pShuzu -> pShuzutou ) ; 
		// 将数组头指针指向新空间
		pShuzu->pShuzutou = pTemp;

	}
	//将数据装进去
	pShuzu->pShuzutou[pShuzu->iShuliang] = iShuJu;  // 数字头[数量]数量的初始值为0
	// 与存储数据量++
	pShuzu->iShuliang++;

}

// 插入数据函数
void ChaRu(struct Dongshuzu* pShuzu, int iShuJu, unsigned int iXiaBiao)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == pShuzu)
	{
		printf("参数错误");
		return;
	}
	//当下表>容量的时候,把该元素添加到最后
	if (pShuzu->iRongliang == pShuzu->iShuliang) // 当容量==数量的时候需要扩容
	{
		// 容量变大
		pShuzu->iRongliang += 10;
		// 申请空间
		int* pTemp = (unsigned int*)malloc(sizeof(unsigned int) * pShuzu->iRongliang);

		// 将源数据复制进新空间
		for (unsigned int i = 0; i < pShuzu->iRongliang; i++)
		{
			pTemp[i] = pShuzu->pShuzutou[i];
		}
		// 将源空间释放
		free(pShuzu->pShuzutou);
		// 将数组头指针指向新空间
		pShuzu->pShuzutou = pTemp;

	}
	//当下标过大
	if (iXiaBiao > pShuzu->iShuliang)
	{
		iXiaBiao = pShuzu->pShuzutou[pShuzu->iShuliang];
	}
	//向后挪
	for (unsigned int i = pShuzu->iShuliang; i >= iXiaBiao; i--)
	{
		pShuzu->pShuzutou[i] = pShuzu->pShuzutou[i - 1];
	}
	// 数据插入到置定位是
	pShuzu->pShuzutou[iXiaBiao] = iShuJu;
	// 数据量++
	pShuzu->iShuliang++;

}

// 将数据输出
void ShuChu(struct Dongshuzu* stshuzu)
{
	//参数检验,如果参数是空程序就为异常,参数有指针的都要进行参数检验
	if (NULL == stshuzu)
	{
		printf("参数错误");
		return;
	}
	printf("容量:%u,数量:%u\n", stshuzu->iRongliang, stshuzu->iShuliang);
	printf("数据:");
	for (unsigned int i = 0; i < stshuzu->iShuliang; i++)
	{
		printf("%d ", stshuzu->pShuzutou[i]);
	}
}

int main(void)
{
	struct Dongshuzu stshuzu;
	ChuShiHua(&stshuzu);

	ZengJia(&stshuzu, 1);
	ZengJia(&stshuzu, 2);
	ZengJia(&stshuzu, 3);
	ZengJia(&stshuzu, 4);

	ChaRu(&stshuzu, 34, 7);
	ChaRu(&stshuzu, 34, 7);
	ChaRu(&stshuzu, 34, 7);
	ChaRu(&stshuzu, 34, 7);


	ShuChu(&stshuzu);

	free(stshuzu.pShuzutou);
	return 0;
}

3.2 修改元素

// 修改指定数据(只修改第一个)
void ChangeByData(struct Node* pHead, int iData1, int iData2)
{
	struct Node* pTemp = FindByData(pHead, iData1);
	if (pTemp != NULL)
	{
		pTemp->iValue = iData2;
	}

}

// 修改替换全部的指定数据
void ChangeALLData(struct Node* pHead, int iData1, int iData2)
{
	if (pHead == NULL)
	{
		printf("输入节点有问题\n");
		return;
	}
	// 第一次找到
	struct Node* pRes = FindByData(pHead, iData1);
	if (pRes == NULL)
	{
		printf("查无此节点\n");
	}
	else
	{
		pRes->iValue = iData2;
	}
	// 查找接下来的数据
	while (pRes != NULL)
	{
		pRes = FindByData(pHead, iData1);
		if (pRes != NULL)
		{
			pRes->iValue = iData2;
		}
	}
	return;
}



// 修改指定下标数据
void ChangeByIndex(struct Node* pHead, int index, int iData2)
{
	struct Node* pTemp = FindByIndex(pHead, 2);
	if (pTemp != NULL)
	{
		pTemp->iValue = iData2;
	}
}

4.查找数据

// 根据数据查找结点
int FindByData(struct Node* pHead, int iData)
{
	while (pHead != NULL)
	{
		if (pHead->iValue == iData)
		{
			return pHead;
		}
		pHead = pHead->pNext;
	}
	return NULL;
}

//根据下标查找结点
int FindByIndex(struct Node* pHead, int iIndex)
{
	int iNum = 1;  // 下标要从1开始,链表下标没有0
	while (pHead != NULL)
	{
		if (iIndex == iNum)
		{
			return pHead;
		}
		iNum++;
		pHead = pHead->pNext;
	}
	return NULL;
}
// 根据数据查找结点

// 根据下表查找结点

# include <stdio.h>

struct Node
{
	int iValue;  //数据
	struct Node* pNext;  // 下一个结点地址
};

// 遍历数据
void Look(struct Node* pHead);

// 查找数据
int FindByData(struct Node* pHead, int iData);

//根据下标查找结点
int FindByIndex(struct Node* pHead, int iIndex);

//展示输出
void ShouData(struct Node* pHead);

int main(void)
{
	struct Node a = { 4,NULL },
				b = { 7,NULL },
				c = { 9,NULL }, 
				d = { 2,NULL };

	a.pNext = &b;
	b.pNext = &c;
	c.pNext = &d;
	Look(&a);

	//查找数据
	struct Node* pFind = FindByData(&a, 8);
	ShouData(pFind);

	// 根据下表查找结点
	struct Node* pIndex = FindByIndex(&a, 2);
	ShouData(pIndex);

	system("pause>0");
	return 0;
}

// 根据数据查找结点
int FindByData(struct Node* pHead, int iData)
{
	while (pHead != NULL)
	{
		if (pHead->iValue == iData)
		{
			return pHead;
		}
		pHead = pHead->pNext;
	}
	return NULL;
}

//根据下标查找结点
int FindByIndex(struct Node* pHead, int iIndex)
{
	int iNum = 1;  // 下标要从1开始,链表下标没有0
	while (pHead != NULL)
	{
		if (iIndex == iNum)
		{
			return pHead;
		}
		iNum++;
		pHead = pHead->pNext;
	}
	return NULL;
}

// 遍历数据
void Look(struct Node* pHead)
{
	// 遍历列表的循环
	while (pHead != NULL)
	{
		printf("%d ", pHead->iValue);
		pHead = pHead->pNext;
	}
	printf("\n");
}


//展示输出
void ShouData(struct Node* pHead)
{
	if (pHead == NULL)
	{
		printf("查无结点\n");
	}
	else
	{
		printf("查到此结点:%d\n", pHead->iValue);
	}
}

二、双向链表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值