数据结构-单链表02

线性表的链式存储结构

单链表结构

将线性表L=(a 0 ,a 1 ,……,a n-1 )中各元素分布在存储器的不同存储块,称为结点,通过地址或指针建立它们
之间的联系,所得到的存储结构为链表结构。表中元素a i 的结点形式如图所示。在这里插入图片描述
其中,结点的data域存放数据元素a i ,而next域是一个指针,指向a i 的直接后继a i+1 所在的结点。于是,线性表
L=( a 0 ,a 1 ,……,a n-1 )的结构如图所示。
在这里插入图片描述
例 设线性表L=(赵,钱,孙,李,周,吴,郑,王),各 元素在存储器中的分布如图所示。
在这里插入图片描述
结点类型描述

typedef int DateType;

typedef struct _node
{
	DateType data;       /* 结点的数据域 */
	struct _node *next;  /* 结点的后继指针域 */
}LISTNODE_T, *LINKLIST;

LISTNODE_T A;
LINKLIST p = &A;

则结构变量A为所描述的结点,而指针变量p为指向此类型结点的指针(p的值为结点的地址),如图
在这里插入图片描述
设p指向链表中结点a
在这里插入图片描述
获取a i ,写作:p->data;而取a i+1 ,写作:p->next->data.。 另外,若指针p的值为NULL,则它不指向任何结点,
此时取p->data或p->next是错误的。
• 可调用C C语言中malloc()函数向系统申请结点的存储空间,例如:

• LINKLIST p;
• p = (LINKLIST)malloc(sizeof(LISTNODE_T));

• 则创建一个类型为LISTNODE_T的结点,且该结点的地址已存入指针变量p中:

基本运算的相关算法

建立单链表
算法思路:依次读入表L=(a 0 ,…,a n-1 )中每一元素a i (假设为整型),若a i ≠结束符(-1),则为a i创建 一结点,然
后插入表尾,最后返回链表的头结点指针H。
算法描述

LINKLIST  Linklist_Create2(void)
{
	LINKLIST Header, r,p;

	DateType val;
	
	//先建立空的头节点header
	Header = (LINKLIST)malloc(sizeof(LISTNODE_T));

	if(NULL == Header)
	{
		puts(" malloc falied ");
		return NULL;
	}

	Header->data = 0;
	Header->next = NULL;
	r = Header;

	while(1)
	{
		puts(" input num (-1 exit)");
		(void)scanf("%d",&val);

		if( -1 == val)
			break;
		p = (LINKLIST)malloc(sizeof(LISTNODE_T));

		if(NULL == p)
		{
			puts(" malloc falied");
			return NULL;
		}
		p->data = val; //存入数据
		p->next = NULL;//

		r->next = p;//r指向新的节点
		r = p;    //移动r到链表尾部

	}

	return Header;

}

设L=(2,4,8,-1),则建表过程如下:
在这里插入图片描述

链表遍历
算法思路:从链表的a 0 起,判断下一个节点的地址是否为NULL,打印出所有的数据

void Linklist_Print(LINKLIST H)
{
	while( H->next )
	{
		printf("%d ",H->next->data);
		H = H->next;
	}
	puts("\n");
}

链表查找-按序号查找
从链表的a 0 起,判断是否为第i结点,若是则返回该结点的指针,否则查找下一结点,依次类推。

LINKLIST Linklist_Get(LINKLIST H, int pos)
{
	LINKLIST p = H;
	int index = -1;
	
	if(pos <0)
	{
		puts(" position is invalid: <0 ");
		return NULL;
	}
	while( p->next && index < pos )
	{
		p = p->next;
		index++;
	}
	if( index == pos)
	{
		return p;
	}
	else
	{
		puts(" position is invalid: >length ");
		return NULL;
	}
}

链表查找-按值查找(定位)
算法思路:从链表结点a 0 起,依次判断某结点是否等于x,若是,则返回该结点的地址,若不是,则查找下一结点
a 1 ,依次类推。若表中不存在x,则返回NULL。

LINKLIST Linklist_Locate(LINKLIST H, DateType val )
{
	
	LINKLIST p = H->next;
	
	while( p && p->data != val)
	{
		p = p->next;
	}
	
	return p;
}

链表的插入:
算法思路:调用算法GetLinklist(h, i-1),获取结点a i-1 的指针p(a i 之前驱),然后申请一个q结点,存入x,并将
其插入p指向的结点之后。插入时的指针变化如图
在这里插入图片描述

   int Linklist_Insert(LINKLIST H, int pos, DateType val)
    {
    	LINKLIST p,q;
    
    	if(0 == pos)
    		p = H;
    	else
    		p = Linklist_Get(H, pos-1);
    	if(NULL == p)
    	{
    		puts("para is invalid");
    		return ERROR;
    	}
    	else
    	{
    		q = (LINKLIST)malloc(sizeof(LISTNODE_T));
    		if(NULL == p)
    		{
    			puts("malloc failed ");
    			return ERROR;
    		}
    		q->data = val;
    		q->next = p->next;
    		p->next = q;
    
    		return SUCCESS;       	
    	}
    }

链表的删除
算法思路:同插入法,先调用函数Linklist_Get(h, i-1),找到结点a i 的前驱,然后如图所示,将结点a i 删除之。
在这里插入图片描述

int Linklist_Delete(LINKLIST H, int pos)
{
	LINKLIST p,q;
	
	if( 0 == pos)
	{
		p = H;
	}
	else
	{
		p = Linklist_Get(H, pos-1);
	}

	if(NULL == p || p->next == NULL  )
	{
		puts("para is invalid ");
		return ERROR;
	}
	else //若p及p->next所在的结点存在
	{
		q = p->next;
		p->next = q->next;
		free(q); //删除结点//
		q = NULL;
		return SUCCESS;
	}

}

单链表倒置
在这里插入图片描述

void Linklist_Reverse(LINKLIST H)
{
	LINKLIST p, q;
	p = H->next;//令指针p指向结点a 0 //
	H->next = NULL;//将原链表置空

	while(p)
	{
		q = p;
		p = p->next;//将结点a i 插入到头结点之后//
		q ->next = H->next;
		H->next = q;
	}
	
}

单链表的有序插入

int Linklist_Order_Insert(LINKLIST H, DateType val)
{
	LINKLIST p,q;

	p = (LINKLIST)malloc(sizeof(LISTNODE_T));
	if(NULL == p)
	{
		puts("malloc failed ");
		return ERROR;
	}
	p->data = val;
	q = H;

	while(q->next && q->next->data < val)
	{
		q = q->next;
	}

	p->next = q->next;
	q->next = p;

	return SUCCESS;
}

单链表的排序

void Linklist_Sort(LINKLIST H)
{
	LINKLIST p,q,r;
	
	p = H->next;
	H->next = NULL;

	while(p)
	{
		q = p;
		p = p->next;
		r = H;
		while( r->next && r->next->data < q->data )
			r = r->next;
		q->next = r->next;
		r->next = q;
	}
}

版权声明
内容摘取华清创客学院培训资料,个人水平有限,感谢华清创客学院的指导和帮助。

©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值