数据结构-链表的操作

文章目录

  • 链表综合程序
    • 主函数
    • 创建链表函数
    • 遍历链表函数
    • 判断链表是否为空函数
    • 判断链表的长度函数
    • 在链表中插入结点函数
    • 对链表中的数据排序函数
    • 删除链表中的结点函数
  • 完整程序


链表综合程序

主函数

# include 
# include   //使用了malloc函数
# include   //使用了exit函数

typedef struct Node
{
     
	int data;              //数据域
	struct Node * pNext;   //指针域
}NODE, *PNODE;   //NODE等价于struct Node,PNODE等价于struct Node *

/*函数声明,可以不写形参名,但是必须声明形参类型*/
PNODE Create_list(void);               //创建链表
void Traverse_list(PNODE);             //遍历链表
bool Is_empty(PNODE);                  //判断链表是否为空
int Length_list(PNODE);                //判断链表的长度
bool Insert_list(PNODE, int, int);     //在链表中插入元素
bool Delete_list(PNODE, int, int *);   //删除链表中的元素
void Sort_list(PNODE);                 //对链表中的数据排序

int main(void)
{
     
	PNODE pHead = NULL;
	int val;  //用于保存被删除的元素

	printf("----------------创建链表----------------\n");
	pHead = Create_list();    //创建链表

	printf("\n----------------遍历链表----------------\n");
	printf("链表中的元素为:\n");
	Traverse_list(pHead);     //遍历链表

	printf("------------判断链表是否为空------------\n");
	if(Is_empty(pHead))       //判断链表是否为空
		printf("链表为空!\n");
	else
		printf("链表非空!\n");

	printf("----------------插入元素----------------\n");
	Insert_list(pHead, 3, 25);      //链表插入结点
	printf("链表中的第3个位置插入元素25后,链表为:\n");
	Traverse_list(pHead);

	printf("----------------元素排序----------------\n");
	Sort_list(pHead);  //对链表中的元素进行排序
	printf("对链表中的元素进行排序后为:\n");
	Traverse_list(pHead);

    printf("--------------判断链表长度--------------\n");
	int len = Length_list(pHead);   //判断链表长度
	printf("链表长度为:%d\n", len);

	printf("----------------删除元素----------------\n");
	if(Delete_list(pHead, 2, &val))  //删除链表中的第2个元素
		printf("删除的是第2个元素:%d\n删除成功!\n", val);
	else
		printf("删除失败!\n");
	printf("删除后链表中的元素为:\n");
	Traverse_list(pHead);

	return 0;
}

创建链表函数

/*创建非循环单链表,并将该链表的首结点地址返回*/
PNODE Create_list(void)
{
     
	int len;    //用于存放有效结点的个数
	int i;
	int val;    //用于临时存放用户输入的结点的值

	/*分配不存放有效数据的头指针*/
	PNODE pHead = (PNODE)malloc(sizeof(NODE)); 
	/*
	    定义一个PNODE(struct Node *)类型的变量pHead,
	    pHead由malloc函数分配内存空间,所占大小为
	    NODE(struct Node)所占大小
	*/
	
	/*判断内存是否分配成功,未成功分配内存则终止程序*/
	if (NULL == pHead)
	{
     
		printf("分配失败!程序终止!\n");
		exit(-1);  //终止程序
	}

	/*分配存储最后一个尾结点的指针*/
	PNODE pTail = pHead;  
	pTail->pNext = NULL;

	/*用户输入链表的长度*/
	printf("请输入您需要生成的链表结点个数:");
	scanf("%d", &len);

	/*用户输入每一个结点的数据*/
	for (i = 0; i < len; i++)
	{
     
		printf("请输入第 %d 个结点的值:", i + 1);
		scanf("%d", &val);

		/*新分配一个结点,用于临时存放用户输入的数据*/
		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		if (NULL == pNew)
		{
     
			printf("分配失败!程序终止!\n");
			exit(-1);  //终止程序
		}

		/*将之后每分配的结点挂在前一个结点后*/
		pNew->data = val;
		pTail->pNext = pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}

	return pHead;  //返回第一个存放有效数据的结点地址
}

数据结构-链表的操作_第1张图片

  • 使用malloc函数动态分配一个头指针(pHead),指向首结点
    • if语句判断头指针是否分配成功(NULL==pHead)
  • 使用malloc函数动态分配一个尾指针(pTail),指向尾结点
    • if语句判断尾结点是否分配成功(NULL==pHead)
  • 当链表中只有一个结点时,pTal就等于pHead,且指针域为空(NULL)
  • 使用for循环,对链表的长度以及元素进行赋值
    • 在循环体内,再动态分配一个临时结点(pNew),用于临时存放新加入结点的数据
    • 将用户输入的值赋值给pNew中的data,同时把pNew中的指针域清空(pNext=NULL)
    • 再使pTail中的pNext指向pNew,即将pNew挂在首结点后
    • 使pTail的值等于pNew,即pTail指向尾结点
  • 最后返回pHead,即存指向首结点的指针

遍历链表函数

/*遍历链表*/
void Traverse_list(PNODE pHead)
{
     
	PNODE p = pHead->pNext;  //定义结点的指针,pHead指向的下一个结点地址

    /*
        判断指向下一个结点地址是否为NULL,是则表明是最后一个结点
        否则输出这个结点中的数据部分,并使p指向下一个结点
    */
	while(NULL != p)
	{
     
		printf("%d ", p->data);
		p = p->pNext;
	}
	printf("\n");

	return;
}

判断链表是否为空函数

/*判断链表是否为空*/
bool Is_empty(PNODE pHead)
{
     
    /*如果头指针指向的下一个结点为NULL,则表明链表中没有结点*/
	if (NULL == pHead->pNext)
		return true;
	else
		return false;
}

判断链表的长度函数

/*判断链表的长度*/
int Length_list(PNODE pHead)
{
     

    /*定义临时结点指针p,p指向首结点*/
	PNODE p = pHead->pNext;
	int len = 0;
	
	/*
	    判断p是否为空,为空则表明是最后一个结点,否则执行长度+1
	    同时把p指向下一个结点
	*/
	while(NULL != p)
	{
     
		++len;
		p = p->pNext;
	}

	return len;  //返回链表的长度
}

在链表中插入结点函数

/*向链表的第pos个结点前插入一个新的结点,值为val*/
bool Insert_list(PNODE pHead, int pos, int val)
{
     
	int i = 0;
	PNODE p = pHead;

	/*
	    pHead指向一个链表,并且插入的位置要大于0,即只能在1之后的位置插入结点,
	    包括1,不能在负数位置插入结点
	    
	    i用来统计链表的长度,插入的位置只能是链表长度的下一个结点,不能
	    是下下一个结点,即中间不能空一个结点
	*/
	while(NULL != p && i < pos - 1)
	{
     
		 p = p->pNext;
		 i++;
	}

	/*如果插入结点的位置大于链表长度+1,或p没有指向一个链表,返回false*/
	if (i > pos - 1 || NULL == p)
		return false;
	
	/*定义一个临时结点,用于存放用户输入的数据*/
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if (NULL == pNew)
	{
     
		printf("动态内存分配失败!\n");
		exit(-1);
	}

	/*将新分配的结点挂在链表上*/
	pNew->data = val;
	PNODE q = p->pNext;
	p->pNext = pNew;
	pNew->pNext = q;

	return true;
}

数据结构-链表的操作_第2张图片

  • 将插入结点的数据赋值给pNew中的data
  • 定义临时结点指针q,用于存放p原本指向的下一个结点
  • 将p中的pNext指向新分配的存放数据的临时结点(pNew)
  • 将pNew中的pNext指向q,即原本p指向的下一个结点

对链表中的数据排序函数

/*对链表中的元素进行排序*/
void Sort_list(PNODE pHead)
{
     
	int i, j, t;
	int len = Length_list(pHead);  //链表长度,用于判断比较的次数
	PNODE p, q;  //用于指向两个不同的结点,便于进行比较

	/*
	    p指向首结点,条件不成立,p则指向下一个结点
	    q指向p的下一个结点,条件不成立,q则指向下一个结点
	    i表示使用第i个结点,j表示与i进行比较的后续结点
	*/
	for (i = 0, p = pHead->pNext; i < len - 1; i++, p = p->pNext)
	{
     
		for (j = i + 1, q = p->pNext; j < len; j++, q = q->pNext)
		{
     
			/*
			    判断第i个结点中的数据是否大于第j个结点中的数据
			    是则互换数据部分,否则与第j个结点的下一个结点进行比较
			*/
			if (p->data > q->data)
			{
     
				t = p->data;
				p->data = q->data;
				q->data = t;
			}
		}
	}
	return;  //表示函数调用结束
}

删除链表中的结点函数

/*删除链表中pos位置的元素*/
bool Delete_list(PNODE pHead, int pos, int * pVal)
{
     
	int i = 0;
	PNODE p = pHead;

	/*
	    p不指向链表中的最后一个结点,
	    p指向删除位置前的一个结点
	*/
	while(NULL != p->pNext && i < pos - 1)
	{
     
		 p = p->pNext;
		 i++;
	}

	/*删除的位置大于链表的长度或者p是最后一个结点,返回false*/
	if (i > pos - 1 || NULL == p->pNext)
		return false;

	/*将删除后的结点挂在删除结点前的结点上*/
	PNODE q = p->pNext;  //定义临时结构体指针,存放删除结点的指针
	*pVal = q->data;  //把删除的数据存放在pVal中

	/*删除p结点后面的结点*/
	p->pNext = p->pNext->pNext;  //使p->pNext跳过被删除的结点,指向下一个结点
	free(q);  //将q结点,即被删除的结点存储空间释放
	q = NULL;  //使q为空

	return true;
}

数据结构-链表的操作_第3张图片

完整程序

/*
	1.创建链表
	2.遍历链表
	3.判断链表是否为空
	4.输出链表长度
	5.在链表中插入结点
	6.对链表中个结点中的数据进行排序
	7.删除链表中的结点
*/
# include 
# include   //使用了malloc函数
# include   //使用了exit函数

typedef struct Node
{
     
	int data;              //数据域
	struct Node * pNext;   //指针域
}NODE, *PNODE;   //NODE等价于struct Node,PNODE等价于struct Node *

/*函数声明,可以不写形参名,但是必须声明形参类型*/
PNODE Create_list(void);               //创建链表
void Traverse_list(PNODE);             //遍历链表
bool Is_empty(PNODE);                  //判断链表是否为空
int Length_list(PNODE);                //判断链表的长度
bool Insert_list(PNODE, int, int);     //在链表中插入元素
void Sort_list(PNODE);                 //对链表中的数据排序
bool Delete_list(PNODE, int, int *);   //删除链表中的元素


int main(void)
{
     
	PNODE pHead = NULL;
	int val;  //用于保存被删除的元素

	printf("----------------创建链表----------------\n");
	pHead = Create_list();    //创建链表

	printf("\n----------------遍历链表----------------\n");
	printf("链表中的元素为:\n");
	Traverse_list(pHead);     //遍历链表

	printf("------------判断链表是否为空------------\n");
	if(Is_empty(pHead))       //判断链表是否为空
		printf("链表为空!\n");
	else
		printf("链表非空!\n");

	printf("----------------插入元素----------------\n");
	Insert_list(pHead, 3, 25);      //链表插入结点
	printf("链表中的第3个位置插入元素25后,链表为:\n");
	Traverse_list(pHead);

	printf("----------------元素排序----------------\n");
	Sort_list(pHead);  //对链表中的元素进行排序
	printf("对链表中的元素进行排序后为:\n");
	Traverse_list(pHead);

    printf("--------------判断链表长度--------------\n");
	int len = Length_list(pHead);   //判断链表长度
	printf("链表长度为:%d\n", len);

	printf("----------------删除元素----------------\n");
	if(Delete_list(pHead, 2, &val))  //删除链表中的第2个元素
		printf("删除的是第2个元素:%d\n删除成功!\n", val);
	else
		printf("删除失败!\n");
	printf("删除后链表中的元素为:\n");
	Traverse_list(pHead);

	return 0;
}

/*创建非循环单链表,并将该链表的首结点地址返回*/
PNODE Create_list(void)
{
     
	int len;    //用于存放有效结点的个数
	int i;
	int val;    //用于临时存放用户输入的结点的值

	/*分配不存放有效数据的头指针*/
	PNODE pHead = (PNODE)malloc(sizeof(NODE)); 
	/*
	    定义一个PNODE(struct Node *)类型的变量pHead,
	    pHead由malloc函数分配内存空间,所占大小为
	    NODE(struct Node)所占大小
	*/
	
	/*判断内存是否分配成功,未成功分配内存则终止程序*/
	if (NULL == pHead)
	{
     
		printf("分配失败!程序终止!\n");
		exit(-1);  //终止程序
	}

	/*分配存储最后一个尾结点的指针*/
	PNODE pTail = pHead;  
	pTail->pNext = NULL;

	/*用户输入链表的长度*/
	printf("请输入您需要生成的链表结点个数:");
	scanf("%d", &len);

	/*用户输入每一个结点的数据*/
	for (i = 0; i < len; i++)
	{
     
		printf("请输入第 %d 个结点的值:", i + 1);
		scanf("%d", &val);

		/*新分配一个结点,用于临时存放用户输入的数据*/
		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		if (NULL == pNew)
		{
     
			printf("分配失败!程序终止!\n");
			exit(-1);  //终止程序
		}

		/*将之后每分配的结点挂在前一个结点后*/
		pNew->data = val;
		pTail->pNext = pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}

	return pHead;  //返回第一个存放有效数据的结点地址
}

/*遍历链表*/
void Traverse_list(PNODE pHead)
{
     
	PNODE p = pHead->pNext;  //定义结点的指针,pHead指向的下一个结点地址

    /*
        判断指向下一个结点地址是否为NULL,是则表明是最后一个结点
        否则输出这个结点中的数据部分,并使p指向下一个结点
    */
	while(NULL != p)
	{
     
		printf("%d ", p->data);
		p = p->pNext;
	}
	printf("\n");

	return;
}


/*判断链表是否为空*/
bool Is_empty(PNODE pHead)
{
     
    /*如果头指针指向的下一个结点为NULL,则表明链表中没有结点*/
	if (NULL == pHead->pNext)
		return true;
	else
		return false;
}

/*判断链表的长度*/
int Length_list(PNODE pHead)
{
     

    /*定义临时结点指针p,p指向首结点*/
	PNODE p = pHead->pNext;
	int len = 0;
	
	/*
	    判断p是否为空,为空则表明是最后一个结点,否则执行长度+1
	    同时把p指向下一个结点
	*/
	while(NULL != p)
	{
     
		++len;
		p = p->pNext;
	}

	return len;  //返回链表的长度
}

/*向链表的第pos个结点前插入一个新的结点,值为val*/
bool Insert_list(PNODE pHead, int pos, int val)
{
     
	int i = 0;
	PNODE p = pHead;

	/*
	    pHead指向一个链表,并且插入的位置要大于0,即只能在1之后的位置插入结点,
	    包括1,不能在负数位置插入结点
	    
	    i用来统计链表的长度,插入的位置只能是链表长度的下一个结点,不能
	    是下下一个结点,即中间不能空一个结点
	*/
	while(NULL != p && i < pos - 1)
	{
     
		 p = p->pNext;
		 i++;
	}

	/*如果插入结点的位置大于链表长度+1,或p没有指向一个链表,返回false*/
	if (i > pos - 1 || NULL == p)
		return false;
	
	/*定义一个临时结点,用于存放用户输入的数据*/
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if (NULL == pNew)
	{
     
		printf("动态内存分配失败!\n");
		exit(-1);
	}

	/*将新分配的结点挂在链表上*/
	pNew->data = val;
	PNODE q = p->pNext;
	p->pNext = pNew;
	pNew->pNext = q;

	return true;
}

/*对链表中的元素进行排序*/
void Sort_list(PNODE pHead)
{
     
	int i, j, t;
	int len = Length_list(pHead);  //链表长度,用于判断比较的次数
	PNODE p, q;  //用于指向两个不同的结点,便于进行比较

	/*
	    p指向首结点,条件不成立,p则指向下一个结点
	    q指向p的下一个结点,条件不成立,q则指向下一个结点
	    i表示使用第i个结点,j表示与i进行比较的后续结点
	*/
	for (i = 0, p = pHead->pNext; i < len - 1; i++, p = p->pNext)
	{
     
		for (j = i + 1, q = p->pNext; j < len; j++, q = q->pNext)
		{
     
			/*
			    判断第i个结点中的数据是否大于第j个结点中的数据
			    是则互换数据部分,否则与第j个结点的下一个结点进行比较
			*/
			if (p->data > q->data)
			{
     
				t = p->data;
				p->data = q->data;
				q->data = t;
			}
		}
	}
	return;  //表示函数调用结束
}

/*删除链表中pos位置的元素*/
bool Delete_list(PNODE pHead, int pos, int * pVal)
{
     
	int i = 0;
	PNODE p = pHead;

	/*
	    p不指向链表中的最后一个结点,
	    p指向删除位置前的一个结点
	*/
	while(NULL != p->pNext && i < pos - 1)
	{
     
		 p = p->pNext;
		 i++;
	}

	/*删除的位置大于链表的长度或者p是最后一个结点,返回false*/
	if (i > pos - 1 || NULL == p->pNext)
		return false;

	/*将删除后的结点挂在删除结点前的结点上*/
	PNODE q = p->pNext;  //定义临时结构体指针,存放删除结点的指针
	*pVal = q->data;  //把删除的数据存放在pVal中

	/*删除p结点后面的结点*/
	p->pNext = p->pNext->pNext;  //使p->pNext跳过被删除的结点,指向下一个结点
	free(q);  //将q结点,即被删除的结点存储空间释放
	q = NULL;  //使q为空

	return true;
}

/*
在Visual C++6.0中的运行结果
-----------------------
----------------创建链表----------------
请输入您需要生成的链表结点个数:4
请输入第 1 个结点的值:12
请输入第 2 个结点的值:11
请输入第 3 个结点的值:24
请输入第 4 个结点的值:13

----------------遍历链表----------------
链表中的元素为:
12 11 24 13
------------判断链表是否为空------------
链表非空!
--------------判断链表长度--------------
链表长度为:4
----------------插入元素----------------
链表中的第3个位置插入元素25后,链表为:
12 11 25 24 13
----------------元素排序----------------
对链表中的元素进行排序后为:
11 12 13 24 25
--------------判断链表长度--------------
链表长度为:5
----------------删除元素----------------
删除的是第2个元素:12
删除成功!
删除后链表中的元素为:
11 13 24 25
Press any key to continue . . .
-----------------------
*/

以上内容均属原创,如有不详或错误,敬请指出。

你可能感兴趣的:(C语言,&,数据结构(专升本)学习笔记)