链表操作集合 - C语言

主要是给自己以后复习知识,还有进行修改优化用的:

欢迎批评,其中链表合并的就地合并我并未掌握,我用了新的头结点以后要补上

首先是头文件定义

#ifndef ANDREW
#define ANDREW

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>


#define SIZE 10

struct Lnode;
typedef int Elemtype;
typedef struct Lnode
{
	Elemtype data;
	struct Lnode *next;  //定义一个struct Lnode 类型的指针
}Lnode,*Linklist; //一个普通类型 一个指针类型

void create_and_insert1(Linklist *pList);//不带头的尾插
void create_and_insert2(Linklist *head); //不带头的头插
void create_and_insert_sort();        //不带头的顺序插
void Showlinklist(Lnode *head);     //打印链表
void create_sort_insert(Linklist* pList) ;


void Shownodelinklist(Lnode *head);    //打印带头结点的链表
Linklist Makeempty();  //初始化
Linklist Makelinklistlast(Linklist head,int n); //尾插
Linklist Makelinklistfront(Linklist head,int n);  //头插
Lnode *Islast(Lnode *head);
Lnode *Find(Linklist L,Elemtype key);
Lnode *Delete(Linklist L,Elemtype key);   //删除所有为key的结点
Lnode *Findprevious(Linklist L,Elemtype key);   //找到key结点的前驱



Linklist Elemfour(Linklist head,int k);
Linklist Middlenode(Linklist head);
Linklist Nizhilinklist(Linklist head); //链表逆置  带头结点
Linklist Sortlinklist(Linklist head);     //**************************************
Linklist Deleteallelement(Linklist head);

#endif 

#include "superman.h"
//无头结点尾插
void create_and_insert1(Linklist *pList)
{
	int number;
	Linklist Tail = *pList =(Linklist)calloc(1,sizeof(Lnode)); //第一个结点已经初始化
	int count=0;
	//srand(time(NULL));
	for(;count!=SIZE;count++)
	{
		if(count==0)
		{
			(*pList) -> data =rand()%100;
		}
		else
		{           //动态分配 不会自动释放,
			Linklist pcur=(Linklist)calloc(1,sizeof(Lnode));   //已初始化完成
// 			printf("the %dst number:\n",count);
// 			scanf("%d",&number);
			pcur->data=rand()%100;
			Tail->next=pcur;
			Tail=pcur;
		}
	}
	
}

//无头结点头插
void create_and_insert2(Linklist *head) //我理解head是一个指向结构体的指针
{
	Lnode *Tail=*head=(Lnode*)calloc(1,sizeof(Lnode));
	int count=0;
	//srand(time(NULL));
	for(;count!=SIZE;++count)
	{
		if(count==0)
		{
			(*head) -> data =rand()%100;
		}
		else
		{
			Lnode *p=(Lnode*)calloc(1,sizeof(Lnode));
			p->data=rand()%100;
			p->next= *head;         //head本身是结构体的地址
			*head=p;
		}
		
	}
}

//顺序插入
void create_and_insert_sort(Linklist *head)    //用两个指针  一个标记前驱
{   
	Linklist pre,last;
	int count=0;
	srand(time(NULL));
	*head =(Lnode*)calloc(1,sizeof(Lnode)); 
	for(;count!=SIZE;++count)
	{
		if(count==0)
		{
			(*head)->data =rand()%100;
		}
		else
		{
			
			Lnode *p=(Lnode *)calloc(1,sizeof(Lnode));  //新插入的结点
			p-> data=rand()%100;
			pre=NULL;
			last=*head;
			while(last)  //定位要插入的位置
			{
				if(p->data>=last->data)
				{
					pre=last;
					last=last->next;
					
				}
				else
					break;
			}
			if(pre==NULL)    // 判断是否在首部插入。插入首部之前
			{
				p->next=*head;
				*head=p;
			}
			else
			{
				p->next = pre->next;
				pre->next= p;
			}
		}

	}
}

//打印链表
void Showlinklist(Lnode *head)
{
	Lnode *p=head;
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
		
	}
	printf("\n");
}

//打印带头结点的
void Shownodelinklist(Lnode *head)
{
	Lnode *p=head->next;
	while(p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;

	}
	printf("\n");
}

Linklist Makeempty()
{
	Lnode *head=(Lnode *)malloc(sizeof(Lnode));
	if(!head)
	{
		printf("Error!\n");
	}
	head->data=SIZE;
	head->next=NULL;
	return head;
}

//带头结点的尾插法 
Linklist Makelinklistlast(Linklist head,int n)   //没有返回值的时候 应该用两个解引用
{
	int i;
	int number;
	Lnode *last=head; //不存储数据的只是指针不用开辟空间,但是存储数据的需要开辟空间。
	for(i=0;i<n;++i)
	{
		Lnode *p=(Lnode *)malloc(sizeof(Lnode));
// 		printf("the %d st number:\n",i+1);
// 		fflush(stdin);
// 		scanf("%d",&number);
		p->data=rand()%100;                     //number;
		last->next=p;
		last=p;
	}
	last->next=NULL;
	return head;
}

//带头结点头插法
Linklist Makelinklistfront(Linklist head,int n)
{
	int i;
	int number;
	Lnode *front=head;
	for(i=0;i<n;++i)
	{
		Lnode *p=(Lnode *)calloc(1,sizeof(Lnode));
// 		printf("the %d st number :\n",i+1);
// 		scanf("%d",&number);
		p->data=rand()%100;                         // number;
		p->next=front->next;
		front->next=p;
	}

	return head;
}

//返回最后一个结点
Lnode *Islast(Lnode *head)
{
	Lnode *p=head;
	while(p->next!=NULL)
	{
		p=p->next;
	}
	return p;
}

//查找某个节点
Lnode *Find(Linklist L,Elemtype key)
{
	Lnode *p=L->next;
	while(p->next!=NULL && p->data !=key)
	{
		p=p->next;
	}
	return p;
}

//删除所有值为KEY的结点
Lnode *Delete(Linklist L,Elemtype key)
{
	Lnode *pre=L;           //循环查找,对头和尾特殊处理
	Lnode *last=pre->next;
	while(last)
	{
		if(last->data==key)
		{
			pre->next=last->next;
			free(last);
			last=pre->next;
		}
		else
		{
			pre=last;
			last=last->next;
		}
	}

	return L;
}

//寻找前驱
Lnode *Findprevious(Linklist L,Elemtype key)
{
	Lnode *p=L;   //从第一个节点开始查找
	while(p->next!=NULL && p->next->data !=key)   //思考是p->next还是判断p!=NULL
	{
		p=p->next;
	}
	return p;
}

//寻找倒数第K个结点 
Linklist Elemfour(Linklist head,int k)
{
	int i;
	Linklist quick,slow;
	quick=slow=head->next;     //判断单链表的长度
	for(i=0;i<k;++i)
	{
		if(quick->next==NULL)
		{
			printf("Error!\n");
			break;
		}
		quick=quick->next;
	}
	while(quick->next!=NULL)
	{
		quick=quick->next;
		slow=slow->next;
	}
	return slow;
}

//找出单链表的中间元素
Linklist Middlenode(Linklist head)
{
	int i=0;
	Linklist quick,slow,longlist;
	longlist=head;
	quick=slow=head->next;
	while(longlist!=NULL)
	{
		longlist=longlist->next;
		i++;
	}
	if(i%2==0)
	{
		while(quick->next->next!=NULL)
		{
			quick=quick->next->next;
			slow=slow->next;
		}
	}
	else
	{
		while(quick->next=NULL)
		{
			quick=quick->next->next;
			slow=slow->next;
		}
	}

//删除无头单链表的一个节点q
Linklist Deletenode(Linklist q)
{
	Elemtype temp;
	Linklist last;
	last=q->next;
	temp=q->data;
	q->data=last->data;
	last->data=temp;
	q->next=q->next->next;
	return q;

}

//单链表逆置
Linklist Nizhilinklist(Linklist head)
{
	Linklist pre,mid,last;
	pre=head->next;

	while(pre->next!=NULL)
	{
		mid=pre->next;
		last=pre->next->next;
		mid->next=head->next;
		head->next=mid;
		pre->next=last;
	}
	return head;
}

//链表合并(新建一个头结点)
Linklist Mergelinklist(Linklist head1,Linklist head2)
{
	Linklist pre1,pre2,tail;
	Lnode *head;
	tail=(Lnode *)calloc(1,sizeof(Lnode));
	head=tail;

	pre2=head2;
	pre1=head1;
	while(pre1  &&  pre2)
	{
		if(pre1->data<pre2->data)
		{
			tail->next=pre1;
			tail=pre1;
			pre1=pre1->next;
		}
		else
		{
			tail->next=pre2;
			tail=pre2;
			pre2=pre2->next;
		} 
	}
	if(pre1)
	{
		tail->next=pre1;
	}
	else if(pre2)
	{
		tail->next=pre2;
	}
	return head;
}

//判断单链表是否有环?
 void Circlelinklist(Linklist head)
 {
	 Linklist quick,slow;
	 slow=quick=head->next;
	 while(quick && quick->next!=NULL)   //可以quick走到链表的终点
	 {
		 quick=quick->next->next;
		 slow=slow->next;
		 if(quick==slow)
		 {
			 printf("it has circle ! \n");
			 break;
		 }
			 
	 }
	 
 }

//判断两个单链表是否相交
 void Intersectlinklist(Linklist head1,Linklist head2)
 {
	 int i,j;
	 Linklist first,second;
	 int dis;
	 i=j=0;
	 first=head1->next;
	 second=head2->next;
	 while(first)
	 {
		 first=first->next;
		 ++i;
	 }
	 first=head1;
	 while(second)
	 {
		 second=second->next;
		 ++j;
	 }
	 second=head2;
	 if(i>j)
	 {
		 dis=i-j;
		while(dis)
		{
			first=first->next;
			dis--;
		}
		while(first&&first->next!=NULL)
		{
			first=first->next;
			second=second->next;
			if(first==second)
			{
				printf("Intersect!!\n");
				break;
			}
		}
	 }
	 else if(i==j)
	 {
		 while(first&&first->next!=NULL)
		 {
			 first=first->next;
			 second=second->next;
			 if(first==second)
			 {
				 printf("Intersect!!\n");
				 break;
			 }
		 }
	 }
	 else
	 {
		 dis=j-i;
		 while(dis)
		 {
			 second=second->next;
			 dis--;
		 }
		 while(first&&first->next!=NULL)
		 {
			 first=first->next;
			 second=second->next;
			 if(first==second)
			 {
				 printf("Intersect!!\n");
				 break;
			 }
		 }
	 }
 }

//单链表排序  插入排序
 Linklist Sortlinklist(Linklist head)
 {
	 //无头指针的排序
	 Linklist pre,pnext,mark,markbehind;
	 mark=head->next;
	 head->next=NULL;  //头部断开作为有序链
	 while(mark)
	 {
		 markbehind=mark->next;//标记操作结点的下一个位置
		 if(mark->data<=head->data)  //比头结点还小 插入头结点前面
		 {
			 mark->next=head;
			 head=mark;
		 }
		 else
		 {
			 pre=head;      //用于记录比较结点和结点的前驱
			 pnext=head->next;
			 while(pnext&&pnext->data<mark->data)  //在有序链中找到合适的位置
			 {
				 pre=pnext;
				 pnext=pnext->next;
			 }
			 mark->next=pre->next;
			 pre->next=mark;

		 }
		 mark=markbehind;

	 }
	 return head;//返回新的头结点
	 
 }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值