单链表基础功能C语言实现

头文件 LinkList.h

#ifndef _LINKLIST_H_			//为了防止头文件的重复包含 
#define _LINKLIST_H_

#include<stdio.h>	//这样在测试文件中可以不引入这两个头文件 
#include<stdlib.h>	

typedef int datatype;

typedef struct node{
	datatype data;		//结点的数据域 
	struct node *next;		//结点的指针域,指向其下一个结点 
}listnode,*linklist; 

linklist list_create1();		//创建一个空链表 ,返回一个指针型的结构体,也就是创建的链表的地址
linklist list_create2();		//创建一个可以用户自己输入数据的链表
 
int list_head_insert(linklist H,datatype value);		//在头结点后面插入数据,输出顺序和输入顺序是反的
int list_insert(linklist H,int pos,datatype value);	//按位置插入元素
int list_order_insert(linklist H,int pos,datatype value);	//实现有序插入 

int list_delete(linklist H,int pos);	//删除链表中的一个元素
 
 
linklist list_get(linklist H,int pos);	//按位置查找一个元素 
linklist list_locate(linklist H,datatype value);	//按值查找一个元素
 
void list_reverse(linklist H);	//将链表反转 
void list_sort(linklist H);	//对单链表进行由小到大排序 
void list_show(linklist H);	//把链表的内容打印出来



linklist list_create1()	//创建一个空链表,即只有头结点 
{
	linklist H;
	
	if((H = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc failed!\n"); 
		return H;
	}
	
	H->data=0;
	H->next=NULL;
	return H;
}


linklist list_create2()	//创建一个可以用户自己输入数据的链表 ,s输出是正序输出 
{
	linklist H,r,p;
	int value;
	//先创建一个空链表 
	if((H = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc failed!\n"); 
		return H;
	}
	
	H->data=0;
	H->next=NULL;
	r=H;   //用一个指针指向链表头结点,方便后续插入元素,保证链表H指向头结点不变 
	
	while(1)
	{
		printf("please input a number(-1 exit):");
		scanf("%d",&value);
		if(value == -1){
			break;
		}
		
		if((p = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc failed!\n"); 
		return H;
		}
		p->data=value;
		p->next=NULL;
		
		r->next=p;
		r=p;
	}
	
	return H;
}


int list_head_insert(linklist H,datatype value)		//在头结点后面插入数据 
{
	//因为是头部插入,所以顺序是反的 
	linklist p;
	
	if((p = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc failed!\n");
		return -1;
	}
	
	p->data=value;
	p->next=H->next;
	H->next=p;
	
	return 0;	//插入成功返回0 
}


int list_insert(linklist H,int pos,datatype value)	//按位置插入元素
{
	linklist p,q;
	if(pos==0)
	{
		p=H;
	}	
	else
	{
		p=list_get(H,pos-1);	//使p指向要插入位置之前的一个元素 
	}
	
	if(p == NULL)
	{
		printf("para is invalid\n");
		return -1;
	}
	else
	{
		if((q = (linklist)malloc(sizeof(listnode))) == NULL)
		{
			printf("malloc failed\n");
			return -1;
		}
		q->data=value;
		q->next=p->next;
		p->next=q;
		return 0;
	}
}


int list_order_insert(linklist H,datatype value)	//实现有序插入
{
	linklist p,q;
	
	if((p = (linklist)malloc(sizeof(listnode))) == NULL)
	{
		printf("malloc failed!\n");
		return -1;	
	}	
	p->data=value;
	
	q=H;
	while(q->next!=NULL && q->next->data < value)
	{
		q=q->next;
	}
	//循环结束后一种情况是q->next==NULL,要插入的数比所有结点值都大 
	//另一种情况是找到了合适的位置,从中间插入 
	p->next=q->next;
	q->next=p;
	
	return 0;
}	
 

int list_delete(linklist H,int pos)	//删除链表中的一个元素
{
	linklist p,q;
	
	if(pos==0)
	{
		p=H;	
	}	
	else
	{
		p=list_get(H,pos-1);	//让指针指向要删除结点的前一个结点 
	}
	
	if(p == NULL || p->next == NULL)	//如果p以及p->next不存在,执行以下代码 
	{
		printf("para is invalid\n");
		return -1;	
	} 
	else
	{
		q=p->next;	//q指向要删除结点 
		p->next=q->next;	//让p指向要删除结点后的那个结点 
		free(q);	//释放要删除结点的内存空间 
		q=NULL;
		return 0;	
	} 
	
}

linklist list_get(linklist H,int pos)	//按位置查找一个元素
{
	linklist p=H;
	int i=-1;	//因为链表下标从0开始 
	
	if(pos<0){
		printf("position is invalid:<0\n");
		return NULL;
	} 
	
	while(p->next&&i<pos)
	{
		p=p->next;
		i++;
	}
	// if(p->next)
	if(i == pos)
	{
		return p;
	}
	else
	{
		printf("position is invalid: > length\n");
		return NULL;
	}
}


linklist list_locate(linklist H,datatype value)	//按值查找一个元素
{
	linklist p=H->next;
	
	while(p && p->data != value)
	{
		p=p->next;	
	} 
	
	return p;
}


void list_reverse(linklist H)	//将链表反转 
{
	linklist p,q;
	
	p=H->next;	//p指向结点 a0
	H->next=NULL; 	//	将原链表置空
	
	while(p!=NULL)
	{
		q=p;
		p=p->next;
		q->next=H->next;
		H->next=q;
	} 
}


void list_sort(linklist H)	//对单链表进行由小到大排序 
{
	linklist p,q,r;
	
	//先把链表一分为2
	p=H->next;
	H->next=NULL;
	
	//当p存在的时候,即H不为空链表 
	while(p)
	{
		q=p;
		p=p->next;
		
		r=H;
		while(r->next!=NULL && r->next->data < q->data)  //当r不等于空且指向的下一个结点值小于value
		{
			r=r->next;	
		} 
		//当循环结束r就指向了待插入的前一个结点
		q->next=r->next;
		r->next=q; 
	}
} 


void list_show(linklist H)		//把链表的内容打印出来
{
	while(H->next) 	//只要H->next不等于空,来做遍历输出
	{
		printf("%d ",H->next->data);
		H=H->next;	
	} 
	printf("\n");
}







#endif

测试文件:testLink.c

#include "LinkList.h"

int main()
{
	linklist H,p;		//声明一个结构体指针H
	int pos,value;
	
	H=list_create2();	//创建一个链表
	list_show(H);	//把链表内容打印出来
	
	
	printf("===============================\n");
	printf("请输入要查找的元素位置pos:");	
	scanf("%d",&pos);
	if((p=list_get(H,pos)) != NULL)
	{
		printf("该位置的结点元素为:%d\n",p->data);
	}
	
	
	printf("===============================\n");
	printf("请输入要查找的元素值value:");
	scanf("%d",&value);
	if((p=list_locate(H,value)) != NULL)
	{
		printf("找到该结点:%d\n",p->data);
	}
	else
	{
		printf("链表中无此结点\n");
	}
	
	
	printf("===============================\n");
	printf("请输入要插入结点的结点位置pos和数据value:");
	scanf("%d%d",&pos,&value);
	if(list_insert(H,pos,value)==-1)
		printf("插入失败!\n");
	list_show(H);
	
	
	printf("===============================\n");
	printf("请输入要删除的结点位置pos:");
	scanf("%d",&pos);
	if(list_delete(H,pos) == -1)
	{
		printf("删除失败!\n");	
	} 
	list_show(H);
	
	
	printf("===============================\n");
	printf("输出从小到大排序后的单链表:\n");
	list_sort(H);
	list_show(H);
	
	
	printf("===============================\n");
	printf("下面实现有序插入,请输入要插入的值:\n");
	scanf("%d",&value);
	list_order_insert(H,value);
	list_show(H);
	
	
	printf("===============================\n");
	printf("输出反序后的链表:\n");
	list_reverse(H);
	list_show(H);
		
	return 0;
	 
}

补充:
不带头结点的单链表反转

struct ListNode* list_reverse(struct ListNode *head){
   if((head == NULL) || (head->next==NULL))  //链表为空,或只有一个结点(无需反转),直接返回
          return head;
     struct ListNode *pre, *cur, *ne;
     pre = head;         //将前面几个节点的地址依次保存在新定义的结构体指针
     cur = head ->next;
     while(cur)
     {
          ne = cur->next;  //如果当前节点不为空,则将其指针域赋给ne指针
          cur->next = pre; //直接将两个指针的指向反转
          pre = cur;           //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
          cur = ne;     
      }
     head->next = NULL;//将原来的第一个节点的指针域赋为空,作为尾节点
     head = pre;            //将原来的尾节点变成新链表的第一个节点
     return head;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值