链表基本操作—逆置 合并

从这一篇博客开始对链表的一些典型操作进行总结(主要是把思路和关键点弄清楚):

(1)逆置-头插法
整个程序代码:

#include<iostream>
using namespace std;
typedef struct node{
        int data;
        struct node *next;
}node;
 
node *create() //创建链表
{
        node *head,*p,*q;
        int i=0;
        int x;
       
        head=(node *)malloc(sizeof(node));
        printf("please input thenode:");
        while(1)
        {
               printf("→");
               scanf("%d",&x); //输入链表data的存放的数据。
               if(x==0) {                    
                       break;
               }
               p=(node *)malloc(sizeof(node));
               p->data=x;
               if(++i==1)
               {
                       head->next=p;
               }
               else
               {
                       q->next=p;
               }
               q=p;
        }
        q->next=NULL;
        return head;
}
 
void print(node*head)  //输出链表
{
        node *p;
        int index=0;
        if(head->next==NULL)
        {
               printf("Link isempty!\n");
               exit(0);
        }
        p=head->next;
        printf("the link is: head");
        while(p!=NULL)
        {
               printf("→ %d",p->data);
               p=p->next;
        }
        printf("\n");
}
 
node * reverse(node*head){  //反置链表
        printf("reverse begin\n");
        node *pCur,*pHead;//pCur指向当前要处理的节点,pHead 为了头插而设置的指针
        pCur=head->next->next;
        head->next->next=NULL;//把第一个节点(头节点的下一个节点)next指向指为NULL。不然print 输出时1->2->。因为刚才把2放到1前面,但1->next=2形成循环了。
        int i=0;
        while(pCur!=NULL)
        {      
               pHead=pCur;
               pCur=pCur->next; //注意刚才pCur和pHead 指向同一节点。为了头插,我需要变换pHead 指针但做次之前一定要把pCur 往下移动。
               pHead->next=head->next;
               head->next=pHead;
        }
        return head;
}
 
int length(node*head) //得到链表的长度
{
        int len=0;
        node *p;
        p=head->next;
        while(p)
        {
               len++;
               p=p->next;
        }
        return len;
}
 
node *search(node*head,int pos) //查找某个节点
{
        node *p;
        int len=length(head);
       
        p=head->next;
        if(pos<0)
        {
               printf("incorrectposition!\n");
               return NULL;
        }
        else if(pos>len)
        {
               printf("incorrectposition!\n");
               return NULL;
        }
        else if(pos==0)
        {
               return head;
        }
       
        if(p==NULL)
        {
               printf("the link isempty!\n");
               return NULL;
        }
        while (--pos)
        {
               p=p->next;
        }
        return p;
}
 
node *del(node*head,int pos) //删除某个节点
{
        node *p,*q;
        int len=length(head);
       
        p=head->next;
        if(pos<0)
        {
               printf("incorrectposition!\n");
               return NULL;
        }
        else if(pos>len)
        {
               printf("incorrectposition!\n");
               return NULL;
        }
        if(p==NULL)
        {
               printf("linkempty!\n");
               return NULL;
        }
        p=search(head,pos-1);
        if(p!=NULL&&p->next!=NULL)
        {
               q=p->next;
               p->next=q->next;
               free(q);
        }
        return head;
}
       
node *insert(node*head,int pos,int x)  //插入某个节点
{
        node *p,*q=NULL;
        q=(node *)malloc(sizeof(node));
        q->data=x;
        if(pos==0)
        {
               head->next=q;
               return head;
        }
        p=search(head,pos);
        if(p!=NULL)
        {
               q->next=p->next;
               p->next=q;
        }      
        return head;
}
int main(){
        node * head=create();
        print(head);
        head=reverse(head); //逆置
        print(head);
        return 0;
}


注意关键点在node * reverse(node *head) 函数也注释部分。
1.写时一定要思路清楚。我要干什么。所以定义了当前节点指针pCur,为了头插与head 指针和head->next 交互的指针pHead。这样定义了分工明确的指针,避免写程序过程中思路混乱。
2.注意开始节点的next 要赋为空,不仅防止print 语句进入循环,也是链表的要求,思维要严密。
3.注意我们创建链表一般创建头指针,可以统一起来。加了头结点,第一个节点地址也被某一个节点next存放,空表和非空表。
输出结果为:

please input the node:→1
→2
→3
→4
→5
→6
→0
the link is: head→ 1 → 2 → 3 → 4 → 5 →
reverse begin
the link is: head→ 6 → 5 → 4 → 3 → 2 →
Press any key to continue
合并:

node * mergeLink(node *head1,node * head2){  //两个非递减链表合并成一个非递减链表
	//记住要有活动指针概念 原链表两个活动指针和合并后的活动指针。
	node *head; //刚开始打算直接用head1或者head2 作为合并后的头节点,感觉一直思路不清晰。
	//干脆创建一个,在开始就给头节点赋值。一步一步来做,思路也清晰。
	/* 初始化头节点必不可少,不然第一次p*/
	
	if(head1->next->data<=head2->next->data){
		head=head1; //把head1链表头结点作为合并后的头结点
	}else{
		head=head2; //把head2链表头结点作为合并后的头结点
	}//不然第一次pCur 指向为NULL,pCur->next 没有空间。
	//head=head1;
	node * p1Cur,* p2Cur ,*pCur;//定义3个活动指针
	//初始化3个活动指针
	p1Cur=head1->next; //p1Cur指向链表1的第一个节点
	p2Cur=head2->next; //p2Cur指向链表2的第一个节点
	pCur=head; //初始化为合并后的头结点
	printf("merge begin\n");
	while(p1Cur!=NULL&&p2Cur!=NULL){
		if(p1Cur->data<=p2Cur->data){ //从第一个节点开始放起
			pCur->next=p1Cur;
			p1Cur=p1Cur->next;
			pCur=pCur->next;
		}else{
			pCur->next=p2Cur;
			p2Cur=p2Cur->next;
			pCur=pCur->next;
		}
	}
	if(p1Cur!=NULL){
		printf("p1Cur not null\n");
		pCur->next=p1Cur;
	}
	if(p2Cur!=NULL){
		printf("p2Cur not null\n");
		pCur->next=p2Cur;
	}
	return head;
}

main 函数:

printf("create link1!\n");
	node * head1=create();
	print(head1);
	printf("create link2!\n");
	node * head2=create();
	print(head2);
	printf("merge link!\n");
	node * mergeHead=mergeLink(head1,head2);
	print(mergeHead);
运行结果:
create link1!
please input the node:→1
→2
→4
→6
→0
the link is: head→ 1 → 2 → 4 → 6
create link2!
please input the node:→2
→3
→5
→8
→9
→0
the link is: head→ 2 → 3 → 5 → 8 → 9
merge link!
merge begin
p2Cur not null
the link is: head→ 1 → 2 → 2 → 3 → 4 → 5 → 6 → 8 → 9
Press any key to continue
逆顺合并
node * reverseMergeLink(node *head1,node * head2){  //两个非递减链表合并成一个非递增链表
	//记住要有活动指针概念 原链表两个活动指针和合并后的活动指针。
	node *head; //刚开始打算直接用head1或者head2 作为合并后的头节点,感觉一直思路不清晰。
	//干脆创建一个,在开始就给头节点赋值。一步一步来做,思路也清晰。
	/* 初始化头节点必不可少,不然第一次p*/
	head=head1; //把head1链表头结点作为合并后的头结点,为了不开辟新的头结点
	node * p1Cur,* p2Cur ,*pHead;//定义3个活动指针, pHead 方便头插的指针
	//初始化3个活动指针
	p1Cur=head1->next; //p1Cur指向链表1的第一个节点
	p2Cur=head2->next; //p2Cur指向链表2的第一个节点
	node * tail;
	if(p1Cur->data<=p2Cur->data){
		tail=p1Cur;
	}else{
		tail=p2Cur;;
	}
	pHead=head; //初始化为合并后的头结点
	printf("merge begin\n");
	while(p1Cur!=NULL&&p2Cur!=NULL){
		if(p1Cur->data<=p2Cur->data){ //从第一个节点开始放起
			pHead=p1Cur;
			p1Cur=p1Cur->next;
			pHead->next=head->next;
			head->next=pHead;
		}else{
			pHead=p2Cur;
			p2Cur=p2Cur->next;
			pHead->next=head->next;
			head->next=pHead;
		}
	}
	if(p1Cur!=NULL){
		printf("p1Cur not null\n");
		while(p1Cur!=NULL)
		{	
			pHead=p1Cur;
			p1Cur=p1Cur->next; //注意刚才pCur和pHead 指向同一节点。为了头插,我需要变换pHead 指针但做次之前一定要把pCur 往下移动。
			pHead->next=head->next;
			head->next=pHead;
		}
	}
	if(p2Cur!=NULL){
		while(p2Cur!=NULL)
		{	
			pHead=p2Cur;
			p2Cur=p2Cur->next; //注意刚才pCur和pHead 指向同一节点。为了头插,我需要变换pHead 指针但做次之前一定要把pCur 往下移动。
			pHead->next=head->next;
			head->next=pHead;
		}
	}
	tail->next=NULL; //这个非常重要,链表末尾就是要指向空。
        return head;
}
main
printf("create link3!\n");
	node * head3=create();
	print(head3);
	printf("create link4!\n");
	node * head4=create();
	print(head4);
	printf("merge link!\n");
	node * revMergeHead=reverseMergeLink(head3,head4);
	print(revMergeHead);

运行结果:
create link3!
please input the node:→1
→2
→4
→5
→0
the link is: head→ 1 → 2 → 4 → 5
create link4!
please input the node:→2
→3
→6
→7
→8
→0
the link is: head→ 2 → 3 → 6 → 7 → 8
merge link!
merge begin
the link is: head→ 8 → 7 → 6 → 5 → 4 → 3 → 2 → 2 → 1
Press any key to continue


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值