408数据结构--单链表

#include
#include  
using namespace std;
typedef struct LNode{
	int data;                        //数据域 
	struct LNode *next;              //指针域 
}LNode,*LinkList;

void initLinkList(LinkList &L);                    //初始链表 
int getLength(LinkList L);                         //获取单链表的长度 
void createLinkListTail(LinkList L);    	       //尾插法建立单链表 
void createLinkListHead(LinkList L);               //头插法建立单链表 
void delLinkListX(LinkList &L,int x);              //删除单链表中值为x的结点 
void delLinkA_B(LinkList &L,int A,int B);          //删除单链表中[A,B]之间的值 
LNode *SearchCommon(LinkList la,LinkList lb);      //找到两个单链表的公共节点 例题:找出两个单词的公共后缀,思想相同 
void merge(LinkList &A,LinkList &B);               //合并两个递增单链表,并按递减顺序存于其中一个链表; 
void splitLinkList(LinkList &A,LinkList &B);       //将单链表A拆分为A,B两个单链表,奇数下标存于A,偶数下标存于B 
void splitHc(LinkList hc,LinkList &A,LinkList &B); //将单链表hc(a1,b1,a2,b2,a3,b3..)拆分为(a1,a2,a3)(b3,b2,b1)分别存于A,B 
void RemoveRepeat(LinkList &L);                    //去除有序单链表中的重复元素 
void RemoveRepeat2(LinkList &L);                   //去除无序单链表中的重复元素 ,并保留绝对值相等的元素唯一一个元素 ,|data|<=n
void linkSort(LinkList &L);                        //排序 
LinkList commonC(LinkList A,LinkList B);           //从AB两个递增有序单链表中找到重复元素产生一个单链表C 
void publicPart(LinkList &A,LinkList B);           //将A,B的公共部分存于A中 
int findK(LinkList L,int k);                       //查找倒数第k个位置的元素,并输出 ;成功返回1,失败返回0
int MajorValue(LinkList L);                        //找主元素,即出现次数超过一半的元素,并输出,找到返回1,找不到返回0 
void Resort(LinkList &L);                          //设线性表{a1,a2,a3,a4,..,an}用单链表存储,设计空间复杂度O(1)的排序算法得到{a1,an,a2,an-1,a3...} 
void output(LinkList L);                           //带头节点的单链表的输出 
void output2(LinkList L);                          //不带头结点的单链表的输出 
int main(){
	/** 
	LinkList L1,L2;
	initLinkList(L1);
	createLinkListTail(L1);
	cout<<"尾插法建立单链表结果为:"<
	

	/** 
	拆分单链表测试 
	LinkList A,B;
	initLinkList(A);
	initLinkList(B);
	createLinkListTail(A);
	splitLinkList(A,B);
	output(A);
	output(B);
	**/
	
	/** 
	去重测试 
	LinkList L;
	initLinkList(L);
	createLinkListTail(L);
	RemoveRepeat(L);
	output(L);
	**/
	/** 
	交集测试 
	LinkList A,B,C;
	initLinkList(A);
	initLinkList(B);
	createLinkListTail(A);
	createLinkListTail(B);
	C=commonC(A,B);
	output(C);
	**/
	
	/** 
	找公共节点测试 
	LinkList A,B,C;
	initLinkList(A);
	initLinkList(B);
	createLinkListTail(A);
	createLinkListTail(B);
	publicPart(A,B);
	output(A);
	**/
	
	/**
	找到倒数第五个元素测试 
	LinkList L;
	initLinkList(L);
	createLinkListTail(L);
	int t=findK(L,5);
	**/
	/**
	LinkList hc,A,B;
	initLinkList(hc);
	initLinkList(A);
	initLinkList(B);
	createLinkListTail(hc);
	
	splitHc(hc,A,B);
	cout<<"hc:";
	output(hc);
	cout<<"----------------------"<
	
	/**去重测试
	LinkList L;
	initLinkList(L);
	createLinkListTail(L);
	RemoveRepeat2(L);
	output(L);
	**/
	
	/**
	寻找主元素
	LinkList L;
	initLinkList(L);
	createLinkListTail(L); 
	int t=MajorValue (L);
	cout<
	
	/**合并单链表
	LinkList A,B;
	initLinkList(A);
	initLinkList(B);
	createLinkListTail(A);
	createLinkListTail(B);
	merge(A,B);
	output(A);
	**/
	/**前后混合测试**/
	LinkList L;
	initLinkList(L);
	createLinkListTail(L);
	Resort(L);
	output(L); 
} 

void initLinkList(LinkList &L){
	L=(LNode*)malloc(sizeof(LNode));
	L->next=NULL;
} 
int getLength(LinkList L){
	LNode *p=L;
	int t=0;
	while(p->next!=NULL){
		t++;
		p=p->next;
	} 
	return t;
} 
//尾插 
void createLinkListTail(LinkList L){
	LNode *p,*q;
	p=L;
	int x;
	cout<<"please input a data:"; 
	cin>>x; 
	while(x!=-1){
		q=(LNode*)malloc(sizeof(LNode));
		q->data=x;
		p->next=q;
		p=q;
		cout<<"please input a data:"; 
		cin>>x; 
	} 
	p->next=NULL;
} 
void createLinkListHead(LinkList L){
	LNode *q;
	int x;
	cout<<"please input a data:";
	cin>>x; 
	while(x!=-1){
		q=(LNode*)malloc(sizeof(LNode));
		q->data=x;
		q->next=L->next;
		L->next=q;
		cout<<"please input a data:";
		cin>>x;
	} 
} 
void delLinkListX(LinkList &L,int x){
	LNode *p=L->next,*pre=L,*q;
	while(p!=NULL){
		if(p->data==x){
			q=p;
			p=p->next;
			pre->next=p;
			free(q);
		}else{
			pre=p;
			p=p->next;
		}
	} 
}
void delLinkA_B(LinkList &L,int A,int B){
	LNode *pre=L,*p=L->next;
	while(p!=NULL){
		if(p->data >= A && p->data <= B){
			pre->next=p->next;
			free(p);
			p=pre->next;
		}else{
			pre=p;
			p=p->next;
		}
	} 
} 
/**
0-1->2->4->9->8->7
          /
0-2->3->5
公共部分为9->8->7
时间复杂度O(max{lena,lenb}) 
**/
LNode *SearchCommon(LinkList la,LinkList lb){
	LNode *p,*q;
	int lena=getLength(la);
	int lenb=getLength(lb);
	int k=0;
	if(lena-lenb>0){
		k=lena-lenb;
		p=la->next;
		q=lb->next;
	}else{
		k=lenb-lena;
		p=lb->next;
		q=la->next;
	}
	while(k--){       //较长的立案表现向前移动k,使得后续长度相同 
		p=p->next;
	}
	while(p!=NULL){
//		output2(p);
		if(p->data==q->data)           //p=q则找到了公共节点 
			return p;
		else{              //p!=q,两个节点同时向后移动 
			p=p->next;
			q=q->next;
		} 
	} 
	return NULL; 
}
//A,B单增,合并后的数列单减 
void merge(LinkList &A,LinkList &B){
	LNode *p=A->next,*q=B->next,*s,*t;
	A->next=NULL;
	//头插逆序 
	while(p!=NULL&&q!=NULL){
		if(p->data <= q->data){
			s=p->next;       //防断链 
			p->next=A->next; //最后指向始终为NULL 
			A->next=p;
			p=s;             //恢复原位 
		}else {
			s=q->next;       //防断链 
			q->next=A->next; //最后指向始终为NULL 
			A->next=q;
			q=s;             //恢复原位 
		}
	}
	while(p!=NULL){
			s=p->next;       //防断链 
			p->next=A->next; //最后指向始终为NULL 
			A->next=p;
			p=s;             //恢复原位
	}
	while(q!=NULL){
			s=q->next;       //防断链 
			q->next=A->next; //最后指向始终为NULL 
			A->next=q;
			q=s;             //恢复原位
	}	
} 
/**
思想:不断使用尾插法
**/ 
void splitLinkList(LinkList &A,LinkList &B){
	LNode *p=A->next;
	A->next=NULL;   //P指向A的第一个元素,A的头结点断开
	int i=0;
	LNode *ra=A,*rb=B; 
	while(p!=NULL){
		if(i%2==0){        //如果下标为偶数,尾插入B
			rb->next=p;
			rb=p;
		}else{             //如果下标是奇数,尾插入A 
			ra->next=p; 
			ra=p;
		}
		i++;
		p=p->next;
	} 
	ra->next=NULL;
	rb->next=NULL;	
} 
//A尾插,B头插 
void splitHc(LinkList hc,LinkList &A,LinkList &B){
	LNode *p=hc->next,*ha=A,*hb=B,*s;
	while(p!=NULL){
		//A尾插 
		ha->next=p;   //插入A 
		ha=p;
		p=p->next;//p向后走
		//B头插 
		s=p->next;//暂存p之后的节点 
		p->next=hb->next;//把hb放在p的下一个,p变成头结点后第一个节点 
		hb->next=p;	  //hb重新回到头结点下一个位置
		p=s;	  //p向后走 
	}  
	
	hc->next=NULL;
	ha->next=NULL; 
}
void RemoveRepeat(LinkList &L){
	LNode *pre=L->next,*p=pre->next;         //pre始终指向p的前一个,重复元素只可能是相同的位置 
	while(p!=NULL){
		if(pre->data==p->data){              //如果重复,pre指向p的下一个 
			pre->next=p->next;
			free(p);
			p=pre->next;                    //释放p后,p还是指向pre的后一个位置 
		}else{                              //不相同二者同时后移 
			pre=p;
			p=p->next; 
		}
	}
	
}
//借助辅助空间,牺牲空间换时间
//时间复杂度O(n) 
void RemoveRepeat2(LinkList &L){
	int n=getLength(L); 
	int vec[n];                        
	for(int i=0;i<n;i++){             //初始化 
		vec[i]=0;
	}
	LNode *p=L,*q,*r;
	int m;
	while(p->next!=NULL){
		m=p->next->data > 0 ?  p->next->data : -p->next->data; 
		cout<<"m="<<m<<endl; 
 		if(vec[m]==0){                //用数组下标标识链表节点的值,第一次出现置为1
		  	vec[m]++;  
		  	p=p->next;
		}
 		else{                         //如果已经出现过,就跳过这个元素
 		 	/**
 		 	1 2 4  4   5
 		 	    p      
 		 	       q   p
			**/
			q=p->next;
			p->next=q->next;
			free(q);	
		}
	} 
	
} 
/**
当前值小的链表往后走 
**/
LinkList commonC(LinkList A,LinkList B){
	LinkList C=(LinkList)malloc(sizeof(LNode));
	LNode *t=C,*p=A->next,*q=B->next;
	t->next=NULL;
	while(p!=NULL && q!=NULL){
		if(p->data==q->data){    //如果是公共元素,放入C中
			LNode *s=(LNode*)malloc(sizeof(LNode));
			s->data=p->data;
			t->next=s;
			t=s;
			p=p->next;
			q=q->next;
		}else if(p->data > q->data){  //p->data  >  q->data    q向后移动
			q=q->next; 
		}else{
			p=p->next;
		}
	} 
	t->next=NULL;
	return C;
}
/**
1-3-4-5
2-3-4-6
公共部分3-4
思想:p指向A,q指向B,小的节点后移 
**/ 
void publicPart(LinkList &A,LinkList B){
	LNode *p=A->next,*q=B->next;
	A->next=NULL;                      //断开头结点
	LNode *r=A;
	r->next=NULL;
	while(p!=NULL && q!=NULL) {
		if(p->data==q->data){
			r->next=p;
			r=p;
			p=p->next;
			q=q->next;
		} else if(p->data > q->data){
			q=q->next;
		}else{
			p=p->next;
		}
	}
	r->next=NULL;
} 
/**
	思想:双指针
	p,q在头部,p先走k步,然后p,q同时走直到q到达表尾,p,q之间的距离就是倒着的k 
	时间复杂度O(n) 
**/ 
int findK(LinkList L,int k){
	LNode *p=L->next,*q;
	q=p;
	int count = 0;
	while(p!=NULL){
		if(count<k) count++;
		else
			q=q->next;
		p=p->next;
	}
	if(count < k) return 0;
	else cout<<q->data<<endl;
	return 1;
} 
//牺牲时间换时间
//时间复杂度O(n),空间复杂度O(n) 
int MajorValue(LinkList L){
	int len = getLength(L);    //L中元素的最大值小于长度
	int vec[len];
	for(int i=0;i<len;i++)     //初始化 
		vec[i] = 0;
	LNode *p=L->next;
	while(p!=NULL) {
		vec[p->data]++; 
		p=p->next;
	}
	for(int i=0;i<len;i++){
		if(vec[i]>len/2){
			cout<<"majorValue="<<i<<endl;
			return 1;
		}
	}
	return 0;
} 
/**
算法思想
1.两个指针交替前行找到中间节点
2.将单链表后半段原地逆序
3.前后两段各自取一个 
**/ 
void Resort(LinkList &L){
	LNode *p=L,*q=L,*r,*s,*t;
	while(p->next!=NULL){
		p=p->next;
		q=q->next;
		if(p->next!=NULL) p=p->next; 
	} 
	cout<<"中间节点的值:"<<q->data<<endl;
	/*  1  2 3 4    5 6 7
		       q
		            p
		               r
	*/
	p=q->next;  //p指向后半段的第一个
	q->next=NULL;//断开前半段
	while(p!=NULL){
		r=p->next;
		p->next=q->next;
		q->next=p;
		p=r; 	
	} 
	s=L->next;
	t=L;
	L->next=NULL;
	p=q->next;
	while(p!=NULL){
		t->next=s;
		t=s;
		s=s->next;
		t->next=p;
		t=p;
		p=p->next; 
	}
	t->next=NULL;
}
void output(LinkList L){
	LNode *p;
	p=L->next;
	while(p!=NULL){
		cout<<p->data<<" ";
		p=p->next;
	} 
	cout<<endl;
}
void output2(LinkList L){
	LNode *p;
	p=L;
	while(p!=NULL){
		cout<<p->data<<" ";
		p=p->next;
	} 
	cout<<endl;
}

你可能感兴趣的:(笔记,数据结构,链表,算法)