链表的定义及概念(附c语言实现链表的初始化、长度计算、排序、插入、删除、显示的函数实现过程)

链表

链表为离散存储的数据结构。由n个节点离散分配,彼此通过指针相连,每个节点只有一个前驱节点和后驱节点,首节点没有前驱节点,尾节点没有后驱节点。

关键概念

  • 首节点:

    第一个有效节点

  • 尾节点:

    最后一个有效节点

  • 头节点:

    第一个有效节点前的那个节点

    头节点不存放有效数据

    加头节点的目的主要是为了方便对链表的操作

  • 头指针:

    指向头节点的指针变量

  • 尾指针:
    指向尾节点的指针变量

链表的优缺点:

  • 优点

    空间没有限制

    插入删除元素较快

  • 缺点

    存取速度很慢


实现链表元素的插入和删除算法(伪代码):

  1. 插入:

    • r=p->pNext; p->pNext=q; q=r->pNext;
    • q->pNext=p->pNext; p->pNext=q;
  2. 删除:

    //直接让第一个节点指向第三个节点去删除第二个节点元素,

    //会使得第二个节点的内存无法释放,从而内存泄漏

    r=p->pNext;

    p-pNext=r->pNext;

    free®;//释放r,防止内存泄漏

初始化创建列表、长度计算、排序、插入、删除、显示的函数实现过程:

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

typedef struct Node
{
	int data;
	struct Node* pNext;
}NODE,*PNODE;

PNODE create_list(void);
void traverse_list(PNODE phead);
void insert_list(PNODE phead, PNODE ins,int pos);
void delete_list(PNODE phead,  int pos);
int length_list(PNODE phead);
void sort_list(PNODE phead);//选择排序算法

int main(void) 
{
	int pos;
	int val;
	int pos_delete;
	PNODE phead = NULL;

	phead = create_list();
	traverse_list(phead);

	sort_list(phead);
	traverse_list(phead);

	printf("请输入需要插入的位置和数值:\n");
	scanf_s("%d",&pos);
	scanf_s("%d", &val);
	NODE in = { val,NULL };
	PNODE insert=&in;
	//insert->data = 90;
	//insert->pNext = NULL;
	insert_list(phead,insert,pos);
	traverse_list(phead);


	printf("输入需要删除的节点位置:\n");
	scanf_s("%d",&pos_delete);
	delete_list(phead,pos_delete);
	traverse_list(phead);
	printf("链表的长度是:%d \n",length_list(phead));
	return 0;

}

PNODE create_list(void) 
{
	int len;
	int i;
	int val;

	printf("请输入需要链表的长度:\n");
	scanf_s("%d",&len);

	PNODE phead = (PNODE)malloc(sizeof(NODE));
	if (phead == NULL) {
		printf("初始化节点失败!\n");
		exit(-1);
	}
	PNODE pTail = phead;//创建一个每次链表尾,在pNew新建一个数据后,用它不停的更新数据
	pTail->pNext = NULL;//初始化尾节点的指针(单链表尾节点的指针域为空)

	for (i = 0; i < len; ++i) {
		printf("please inpute %d number: \n",i+1);
		scanf_s("%d",&val);
		PNODE pNew = (PNODE)malloc(sizeof(NODE));
		if (pNew == NULL) {
			printf("初始化节点失败!\n");
			exit(-1);
		}
		else
		{
			pNew->data = val;//下一个节点得到数据
			pTail->pNext = pNew;//之前的尾节点指针域(pTail)更新为新尾节点(pNew)位置
			pNew->pNext = NULL;//新尾节点的指针域改为NULL;此时前尾节点的指针域指向新的尾节点,新的尾节点完成数据更新
			pTail = pNew;//pNew变成新的尾节点pTail
			
		}
		
	}
	return phead;
}

void traverse_list(PNODE phead)
{
	if (phead->pNext == NULL)
		printf("链表为空!\n");
	else
	{
		PNODE p = phead->pNext;
		while (p!=NULL)
		{
			printf("%d ",p->data);
			p = p->pNext;
		}
		printf("\n");
	}
}

int length_list(PNODE phead)
{
	int len = -1;//因为从头节点开始计数的
	if (phead->pNext == NULL)
		printf("链表为空!\n");
	else
	{
		while (phead!=NULL)
		{
			len++;
			phead = phead->pNext;
		}
	}
	return len;
}


void insert_list(PNODE phead,PNODE ins,int pos) 
{
	int i;
	if (phead->pNext == NULL)
		printf("链表为空!\n");
	else if(0 < pos&&pos < length_list(phead)+2)
	{
		PNODE pN = NULL;

		for (i = 1; i < pos; ++i) {
			phead = phead->pNext;//得到前一个节点信息
		}
		pN = phead->pNext;//得到下一个节点信息
		ins->pNext = pN;
		phead->pNext = ins;
	}
	else
	{
		printf("该位置不存在或操作违法!\n");
	}
	return;
}

void delete_list(PNODE phead, int pos)
{
	int i;
	if (phead->pNext == NULL)
		printf("链表为空!\n");
	else if (0 < pos &&pos < length_list(phead))
	{
		PNODE pN,pNN;
		for (i = 1; i < pos; ++i) {
			phead = phead->pNext;//得到前一个节点的信息
		}
		pN = phead->pNext;
		pNN = pN->pNext;
		phead->pNext = pNN;
		free(pN);
	}
	else
	{
		printf("该位置不存在!\n");
	}
	return;
}

void sort_list(PNODE phead)
{
	int i,j,len,r;
	len = length_list(phead);
	if (phead->pNext == NULL)
		printf("链表为空!\n");
	else
	{
		PNODE p,pN;
		p = phead->pNext;
		pN = p->pNext;
		for (i = 0; i < len-1; ++i) {
			for (j = i+1; j < len; ++j) {
				
				if (p->data > pN->data)
				{
					//使用链表中的值域完成对链表的排序,比修改指针域快捷
					r = p->data;
					p->data = pN->data;
					pN->data = r;
				}
				pN = pN->pNext;
			}
			p = p->pNext;
			pN = p->pNext;

		}
	}
	return;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值