08、单链表编程考点

单链表编程考点

1、将单链表的第一个结点放在单链表的最后一个结点的后面

/*
设h是无头结点的单链表,如果线性表h的长度不小于2,则将首元结点删除并插入到表尾
将单链表的第一个结点放在单链表的最后一个结点的后面
*/
typedef struct node
{
	elementype data;
	struct node *next;
}*linklist;

void change(linklist &h)    //linklist &h等价于struct node *&h,这样就可以修改指针h的值;此时不需要return返回已经修改的单链表的值
{
	linklist p,q;			//linklist p,q等价于struct node *p、struct node *q;
	if(h && h->next)		//如果链表中有不少于2个结点
	{
		q = h;				//令p指向第1个结点h
		h = h->next;		//令h指向第2个结点
		p = h;				//令p指向第2个结点
		while(p->next)		//第一次循环时,判断第2个结点的指针域是否为空,如果为空则只有两个结点,则不需要找到最后的一个结点,否则一直循环,找到最后一个结点为止
			p = p->next;	//顺着p开始往下找,一直找到最后一个结点
		p->next = q;		//将第一个结点接在最后一个结点后面
		q->next = NULL;		//新的尾结点没有后继,置后继为空
	}
}
/*
	分析:1、在if判断语句中h为单链表的某一指针指向单链表中的某一个结点
		  2、q = h;此语句的含义是另外一个指针q与指针h同时指向同一个结点
		  3、h = h->next;此语句中的h->next所表示的含义是h->next指向单链表中h指针指向的下一个结点,与此同时h指针和h->next指针同时指向该结点
*/

 

typedef struct node
{
	elementype data;
	struct node *next;
}*Linklist;

Linklist mynode(LinkList L)		//L是不带头结点的单链表的头指针
{
	if(L && L->next)			//如果链表中有不少于2个结点
	{
		q = L;					//令p指向第1个结点h
		L = L->next;			//令h指向第2个结点
		p = L;					//令p指向第2个结点
		while(p->next)
		p = p->next;			//顺着p开始往下找,一直找到最后一个结点
		p->next = q;			//将第一个结点接在最后一个结点后面
		q->next = NULL;			//新的尾结点没有后继,置后继为空
	}
	return L;
}

 

2、实现单链表的删除算法,删除成功返回1,删除失败返回0

/*实现单链表的删除算法,删除成功返回1,删除失败返回0*/
typedef struct node
{
	elementype data;
	struct node *next;
}*LinkList, LNode;

int ListDelete(LinkList L, int i, ElemType *s)        //s是存储将要删除的值,i是将要被删除元素的指定位置
{
	LNode *p,*q;								  	  //定义了两个新的指针变量p、q;
	int j;
	p = L;											  //p指向L单链表的第一个结点元素
	j = 0;
	while((p->next != NULL)&&(j < i-1))				  //j < i-1此处的判断条件是i-1的原因是当最后一次,不满足条件之前,j的值自动增加了一位
	{
		p = p->next;								  //而我们进行删除操作的前提是找到被删除结点元素的前驱结点
		j++;										
	}
	if(p->next == NULL || j > i-1)
		return 0;									//如果if语句成立,将执行return 0;语句,运行过程终止
	q=p->next;										//否则将q指针指向p->next指针所指的结点,即指向被删除结点元素										
	*s = q->data;
	p->next = q->next;								//此语句将指定位置的结点删除,p->next所代表的是被删结点元素的前驱结点的next指针域,而q->next指向被删结点元素的后继结点
	free(q);										//释放结点占有的存储空间
		return 1;
}

 

3、尾插法建立单链表

//尾插法建立单链表
typedef struct node
{
	int data;
	struct node *next;
}lklist;
void lklistcreate(lklist *&head ,int n)					//n表示单链表的长度
{
	lklist *q;											//定义一个新的结点指针	
	for(i = 1;i<=n;i++)
	{							
		p=(lklist *)malloc(sizeof(lklist));				//创建一个新的结点
		scanf("%d",&(p->data));							//获取该结点的数值
		p->next = NULL;
		if(i==1)
			head = q = p;								//head = q = p;该语句表示头指针head,新的结点指针q都指向结点p;
		else
		{
			q->next = p;								//注意:定义的新的结点指针q的作用是通过移动该指针的指向,来实现链表的创建,将q结点的next指针域指向最新创建的结点
			q=p;										//将结点连接以后,再改变q指针的指向,为下一次新结点的创建作好准备
		}
	}
}

  

4、逆转线性单链表,采用是头插法

//逆转线性单链表,采用是头插法
typedef struct node					//就地逆置单链表
{
	elemtype data;
	struct node *next;
}node;
node *Reverse (node *head)			//head是带头结点的单链表
{
	node *p ,*q;
	p = head->next;					//p指向第一个元素
	head->next=NULL;				//保留第一个元素,将头结点的指针域置空
	while(p!=NULL)					//将原链表的元素用头插法插入新的链表中
	{
		q=p;						//令q指向链表的当前第一个元素
		p=p->next;					//p指针后移
		q->next = head->next;		//在新表中插入结点q
		head->next = q;
	}
	return head;
}

  

5、在带头结点的单链表L中,删除所有值为x的结点

//在带头结点的单链表L中,删除所有值为x的结点
typedef struct LNode
{
	Elemtype data;
	struct LNode *next;
}LNode, *Linklist;
void delete(Linklist &L ,ElemType x)
{
	LNode *q=L;
	LNode p=L->next;			//初始化p指向第一个结点,q始终指向p结点的前驱
	while(p!=NULL)
	{
		if(p->data == x)		//若p指针指向当前结点的值等于x
		{
			q->next = p->next;
			free(p);			//删除该结点,并修改p指针
			p=q->next;			//寻找链表中下一个值为x的结点
		}
		else
		{
			q=p;
			p=p->next;			//先使q后移,p向后移动
		}
	}
}

  

6、有序递增序列,删除所有值大于mink且小于maxk的元素

//有序递增序列,删除所有值大于mink且小于maxk的元素
typedef struct node					//就地逆置单链表
{
	elemtype data;
	struct node *next;
}node;
void Delete_Between(node *head, int mink, int maxk)
{
	node *p = head, *q;
	while(p->next->data <= mink)			//p是最后一个不大于mink的元素
	   p=p->next;
	if(p->next)								//如果还有比mink更大的元素
	{
		q=p->next;
		while(q->data<maxk)					//q是第一个不小于maxk的元素
		q=q->next;							//while循环结束以后,q指向比maxk值还大的结点元素
		p->next = q;						//此语句是删除所有值大于mink且小于maxk的元素						
	}
}

  

7、将带头结点单链表h1和h2合并成升序排列的单链表

//将带头结点单链表h1和h2合并成升序排列的单链表
typedef struct L
{
	int data;
	struct L *next;
}LinkL;
LinkL *mergeList(LinkL *h1, LinkL *h2)
{
	LinkL *h, *Next, *q;
	h=h1;
	Next = h;
	h1=h1->next;								//表h1的第一个结点
	h2=h2->next;								//表h2的第一个结点
	while(h1 != NULL && h2 != NULL)				//如果表h1和h2均不为空表
	{
		if(h1->data <= h2->data)				//如果h1指针所指向当前结点的值小于h2
		{										//指针所指向的当前结点的值
			q=h1;								//则令q暂存h1指针所指向的结点
			h1=h1->next;						//h1指针向后移动
		}
		else										//如果h2指针所指向当前结点的值小于h1
		{											//指针所指向的当前结点的值
			q=h2;									//则令q暂存h2指针所指向的结点
			h2-h2->next;							//h2指针向后移动
		}
		Next->next = q;					//将指针p所指向的结点接在Next指针所指的结点后面
		Next = q;						
	}
	if(h1 == NULL)						//如果原h2链表中所有结点已插入但是原h1链表还有结点没插完,则直接把剩余部分接在next指针后面。要是原h1表的所有结点已经全部插完但是h2还有结点没插完,亦是如此
	Next->next = h2;
	if(h2 == NULL)
	Next->next = h1;
	return h;							//返回新表的指针
	
}

  

8、用单链表lc表示集合C,分别将la中的元素取出,再在lb中进行查找,如果在lb中出现,则将其插入到lc中

//将单链表A分解成一个小于零的单链表和大于零的单链表
typedef struct node					
{
	elemtype data;
	struct node *next;
}*LinkList,Linknode;
void decompose(LinkList La,LinkList Lb,LinkList Lc)
{
	Linknode *p;								
	Lc=(Linknode *)malloc(sizeof(Linknode));	
	Lc->next = NULL;							//表C的头结点的next域置空
	p=La->next;									//令p指向表A的第一个元素结点
	Lb=La;										//令Lb指向表La
	Lb->next = NULL;							//令表La的next域置空
	while(p)									//遍历原表A
	{
		La=p->next;								//令La暂存p结点的后继指针
		if(p->data >0)							//如果p结点值大于0,则接在表C后面
		{
			p->next=Lc->next;
			Lc->next = p;
		}
		else{									//如果p结点的值小于0,则接在表B后面
			p->next =Lb->next;
			Lb->next = p;
		}
		p=La;									//令p指向原p所指向的结点的下一个位置
	}
}

  

9、将单链表A分解成一个小于零的单链表和大于零的单链表

//用单链表lc表示集合C,分别将la中的元素取出,再在lb中进行查找,如果在lb中出现,则将其插入到lc中
typedef struct node					
{
	elemtype data;
	struct node *next;
}*LinkList,LNode;
void interaction(LinkList la, LinkList lb, LinkList &lc)
{
	LinkList pa ,pb, pc;
	lc = new LNode();								//生成lc的头结点
	pc=lc;											//pc永远指向lc的尾结点
	pa=la->next;									//pa指向la的第一个元素
	while(pa)
	{
		pb=lb->next;								//pa指向lb表的第一个元素
		while(pb && pb->data != pa->data)
			pb=pb->next;							//在pb中查找元素,使其值等于pa->data
			if(pb)									//如果存在这样的元素
			{
				pc->next = new LNode();				//生成lc新的尾结点
				pc = pc->next;						//pc指向新的尾结点
				pc->data= pa->data;					//将pa->data复制到pc中
			}
			pa=pa->next;							//继续比较pa表的下一个结点元素
	}
	pc->next =NULL;									//pc为尾结点,pc表比较完成后,置pc后继为空
}
 

  

10、已知指针hb和ha分别指向两个单链表的头结点,长度为m和n,假设hc指向连接后的链表的头结点

//已知指针hb和ha分别指向两个单链表的头结点,长度为m和n,假设hc指向连接后的链表的头结点
typedef struct node					
{
	elemtype data;
	struct node *next;
}LinkList; 
void ListConcat(LinkList ha, LinkList hb, LinkList *hc)
{	
	LinkList p;                     //把链表hb接在ha后面形成链表hc
	hc=ha;							//由指针p指向ha的尾元结点
	while(p->next !=NULL)			//查找原ha表的最后一个结点
	p=p->next;
	p->next = hb->next;				//把hb表的第一个元素及其后面元素接在p指针指向的结点后面
	free(hb);
}

  

11、删除单链表中重复的元素

//删除单链表中重复的元素
typedef struct node					
{
	elemtype data;
	struct node *next;
}LinkedList ,*LNode; 
LinkedList DeleteSameElement(LinkedList L)
{									//L为递增有序的单链表
	LNode u;
	LinkedList p, pre;
	pre = L->next;					//pre指针指向第一个元素结点
	p= pre->next;					//p指向pre所指结点的后继结点
	while(p!=NULL)					//如果p指针不为空
	if(p->data == pre->data)		//p所指结点的值等于pre所指结点的值
	{
		u=p;						//用指针u暂存p指针所指向的结点
		p=p->next;					//p指针后移
		free(u);					//释放掉u指针所值结点的内存空间
	}
	else{							//p和pre两指针所指向的结点值不相等
		pre = p;					//pre指针后移
		p = p->next;				//p指针后移
	}
}

  

12、交换单链表中指针p所指结点与其后继结点

//交换单链表中指针p所指结点与其后继结点
typedef struct node					
{
	elemtype data;
	struct node *next;
}*LinkList; 
int exchange(Linklist &head,Linklist p )
{
	LinkList q=head->next;				//q指向第一个元素结点
	LinkList pre=head;					//pre指向头结点
	while(q!=NULL && q!=p)		        //顺着链表开始查找,一直到q=p
	{
		pre=q;
		q=q->next;
	}
	if(p->next ==NULL)			        //退出循环之后,若p无后继,则交换失败
	return 0;
	else{
		q=p->next;
		pre->next = q;
		p->next = q->next;
		q->next = p;
	}
	return 1;
}

  

13、设有一个无序单链表
  1)找出最小值结点
  2)若该数是奇数将与其直接后继结点的数值交换
  3)该数值是偶数将直接后继结点删除

 /*
设有一个无序单链表
1、找出最小值结点
2、若该数是奇数将与其直接后继结点的数值交换
3、该数值是偶数将直接后继结点删除
*/
typedef struct node					
{
	elemtype data;
	struct node *next;
}LinkList; 
void OutputMin(LinkList L)
{
	int temp;
	LinkList q = L->next;				//p指向第一个元素结点
	LinkList p= q;
	while(q)
	{									//找出最小值结点p,并打印p结点数值
		if(p->data >q->data)
			p=q;						//如果发现还有比p指针所指结点的值更小的结点,令p指向该结点,否则q后移
			q=q->next;
	}
	printf("%d",p->data);
	if(p->next != NULL)					//找到了值最小的结点,若该结点有后继结点
	{
		if(p->data % 2 == 1)			//如果该最小值是奇数,则与其后继结点交换
		{
			temp=p->data;
			p->data =p->next->data;
			p->next->data = temp;
		}
		else							//如果该最小值是偶数,则删除其后继结点
		{
			q=p->next;
			p->next = q->next;
			free(q);
		}
	}
}

  

  

posted @ 2017-08-31 21:09  樱桃挚爱丸子  阅读(626)  评论(0编辑  收藏  举报