算法设计学习:单链表算法

(1)题目:单链表A 和 B (带表头结点),元素递增有序。设计算法将A 和 B归并成一个按照元素值依然递增有序的链表C,C由A和B的结点组成。

分析:A,B有序,可以从A,B中挑出最小的元素插入C的尾部。若是一个插入完毕,另一个则只要链接到C的尾部。

代码

typedef struct LNode
{
	int data;
	struct LNode *next;  //指向后继结点的指针
}LNode;

void mergeLinkedList( LNode *&A, LNode *&B, LNode *&C)  //要改变的变量使用引用型
{
	LNode *p = A->next;	 //p 跟踪A的最小值结点
	LNode *q = B->next;	 //q 跟踪B的最小值结点
	LNode *r;			 //r 指向C的终端结点

	C = A;				  //使用A头结点作为C的头结点
	C->next = NULL;
	free(B);			 // B的头结点无用,释放掉
	r = C;				  //头结点

	while( NULL != p && NULL != q )
	{
		if ( p->data <= q->data )
		{
			r->next = p;
			p = p->next; // A移动元素
			r = r->next; // C尾结点向后移动
		}
		else
		{
			r->next = q;
			q = q->next; // B移动元素
			r = r->next; // C尾结点向后移动
		}
	}

	r->next = NULL;		//此句话可以去掉,下面两个if语句必须有一个要执行

	if ( NULL != p )	   //还有剩余结点的链表链接在尾部
	{
		r->next = p;
	}
	if ( NULL != q )
	{
		r->next = q;
	}
}
总结:1)尾插法建立单链表;2)单链表归并操作


引申:归并称为  递减的链表C。  (将插入过程改为头插入法即可)

代码:

void mergeLinkedListDescend( LNode *&A, LNode *&B, LNode *&C)
{
	LNode *p = A->next;	 //p 跟踪A的最小值结点
	LNode *q = B->next;	 //q 跟踪B的最小值结点
	LNode *s;			 //用 S来接受新的结点插入链表C的前端

	C = A;				  //使用A头结点作为C的头结点
	C->next = NULL;
	free(B);			 // B的头结点无用,释放掉

	while( NULL != p && NULL != q )
	{
		if ( p->data <= q->data )	//链表的头插入法
		{
			s = p;		 //将 p 赋值给 接受新结点的 s
			p = p->next; // A移动元素

			s->next = C->next;	// s 所指向新结点的指针域next 指向C中的开始结点
			C->next = s;        // 头结点的指针域next指向 s结点,使得s称为新的开始结点
		}
		else
		{
			s = q;  	//将 q 赋值给 接受新结点的 s
			q = q->next; // B移动元素

			s->next = C->next;	// s 所指向新结点的指针域next 指向C中的开始结点
			C->next = s;        // 头结点的指针域next指向 s结点,使得s称为新的开始结点
		}
	}

	while ( NULL != p )	   //还有剩余结点的链表逐个插入到C的头部
	{
		s = p;		 
		p = p->next; 
		s->next = C->next;	   //  这两句插入顺序不能颠倒。	 后继结点先写
		C->next = s;  			// 这两句插入顺序不能颠倒。
	}
	while ( NULL != q )
	{
		s = q;  
		q = q->next; 
		s->next = C->next;	
		C->next = s;     
	}
}

(2)题目:查找链表C(带头结点)中是否存在一个值为 x 的结点,若存在,则删除该结点并返回1,否则返回0.

代码:

int SearchAndDelete(LNode *&C, int x)
{
	LNode *p;
	LNode *q;
	p = C;
	//查找部分 开始
	while( NULL != p)
	{
		if ( x == p->next->data )
		{	 
			break;
		}
		p = p->next;
	}
	 //查找部分结束
	if ( NULL == p->next )
	{
		return 0;
	}
	else
	{
		//删除部分开始
		q = p->next;
		p->next = p->next->next;   //将p的指针域next指向原来p的下一个结点的下一个结点,即可删除  或者写成  p->next = q->next;
		free(q);	//释放q所指结点的内存空间
		//删除部分结束
		return 1;
	}
}

附录:假设有n个元素已经储存在数组a中,下面分别是尾插法与头插法建立链表C

  //尾插法
void CreateListR(LNode *&C, int a[], int n)
{
	LNode *s;  //s用来指向新申请的结点
	LNode *r;  //r指向C的终端结点
	int i;
	C = (LNode*) malloc( sizeof(LNode));	  //  申请C的头结点空间
	C->next = NULL;
	r = C;
	for ( i = 1; i <= n; ++ i )
	{
		s = (LNode*) malloc( sizeof(LNode));   //s指向新申请的结点
		s->data = a[i];    //新申请的结点接收a的一个元素
		r->next = s;		//r来接纳新结点
		r = r->next;		//r指向终端结点,以便接纳下一个到来的结点
	}
	r->next = NULL;	  //a中的元素全部装入链表C中,C的终端指针为NULL
}

//头插法
void CreateListF(LNode *&C, int a[], int n)
{
	LNode *s;
	int i;
	C = (LNode*) malloc( sizeof(LNode));	  //  申请C的头结点空间
	C->next = NULL;
	for ( i = 1; i <= n; ++ i )
	{
		s = (LNode*) malloc( sizeof(LNode));   //s指向新申请的结点
		s->data = a[i];    //新申请的结点接收a的一个元素
		 /*  下面两句为 头插法 的关键步骤*/
		s->next = C->next;			//s所指新结点的指针域next指向C中的开始结点
		C->next = s;			   //头结点的指针域next指向s结点,使得s成为了新的开始结点
	}
}
<pre name="code" class="cpp">//整表删除
int ClearList(LNode *&C)
{
	LNode *p;
	LNode *q;
	p = C->next;

	while(p)
	{
		q = p->next;
	    free(p);
		p = q;
	}
	C->next = NULL;
	return 1;
}

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值