0
点赞
收藏
分享

微信扫一扫

数据结构-线性表-2单链表

小布_cvg 2022-03-21 阅读 71
#include<stdio.h>
#include<stdlib.h>

//先来归纳一下malloc怎么用:目前用过都是对指针-(指针类型)malloc(sizeof(指向对象类型)) 
/*
顺序表-插入删除不方便都要移动、预先静态分配(难以确定规模有溢出风险)
下面介绍单链表 
*/ 
#define ElemType char
//搞清楚概念:头指针,头节点、数据域+指针域、空

//Node *和LinkList同为结构指针类型,不同的是LinkList往往用来强调是头指针变量,而Node *往往被用来定义指向单链表中结点的指针 
typedef struct Node
{
	ElemType data;
	struct Node *next;
 } Node, *LinkList;
 
//单链表判空分为带头结点和不带头节点两种(假设L是头指针,对应判断方式是 L->next==NULL 或 L == NULL) 
//基本操作:初始化、建立、查找、求长度、插入、删除 

//说实话不太理解为什么要构造一个指向头指针的指针L 
//初始化:注释写在前面:第一行建立头结点、第二行初始化链表为空 
void InitList(LinkList *L)
{
	*L = (LinkList)malloc(sizeof(Node));
	(*L)->next=NULL;
}
 
//建立单链表(头插法、尾插法)
//L是带头结点的空链表头指针(L->next=Null) 
void CreateFromHead(LinkList L)
{
	Node *s;
	char c;
	flag = 1;//判断是否终止
	while(flag)
	{
		c=getchar();
		if(c!='$')
		{
			s=(Node *)malloc(sizeof(Node));
			s->data=c;
			s->next=L->next;
			L->next=s;
		}
		else{
			flag=0;
		}
	 } 
 } 

//头插法建表结点次序与输入次序相反 
void CreateFromTail(LinkList L){
	Node *s, *r;//r是表尾指针
	r=L; 
	char c;
	int flag;
	while(flag)
	{
		c=getchar();
		if(c!='$')
		{
			s->data=c;
			r->next=s;
			r=s;
		}
		else{
			flag=0;
			r->next=NULL;//不同于头插法,这里需要自己设置为空(尾插法破坏了一开始的NULL) 
		}
	 } 
}

//查找:按序号查找和按元素查找

//按序号在带头结点的单链表中查找第i个结点,返回指向改结点的指针 
Node *Get(LinkList L, int i)
{
	if(i<=0) return NULL;
	int j=0;//计数器
	Node *p;//记忆当前指针 
	p=L->next;//觉得这里改成这样:因为头结点实际上是第0个结点 
//终止条件:如果p为NULL即为p是单链表尾指针的指针域 
	while((p!=NULL)&&(j<i)){
		p=p->next;
		j++;
	}
	if(i==j) return p;
	else return NULL;//找不到(i超出链表长度) 
 } 
 
//按值查找

Node *Locate(LinkList L, ElemType key)
{
	Node *p;
	p=L->next;
	//终止条件: p!=NULL;这恰好保证了如果没有对应元素key我们返回p会是NULL 
	while(p->next!=NULL){
		if(p->data!=Key)
			p=p->next;
		else
			break;
	}
	return p;
 } 

//求单链表长度操作
int ListLength(LinkList L)
{
	Node *p;
	p=L->next;//p是头结点的指针域,指向真正的链表首结点 
	int j=0;
	while(p!=NULL)
	{
		j++;
		p=p->next;
	 } 
	return j;
 } 

#define ERROR 0
#define OK 1
//用pre指示第(i-1)个结点 
//单链表插入
//插入共有n+1个位置(头结点一直到尾结点后),对应i的取值可以是1到n+1 
int InsList(LinkList L, int i, ElemType e)
{	
//第一步是从头结点开始查找第(i-1)个结点,实际上头结点就是我们的第0个结点
//pre是指向第i-1个结点的指针,指向头结点的指针就是L
//最坏的情况就是pre到了NULL即尾结点的指针域还没有找到第(i-1)个结点 ,这说明i越界了 
	Node *pre, *s;
	pre=L; 
	int j=0;
	if(i<=0) return ERROR; 
	while((pre!=NULL)&&(j<i-1))
	{
		j++;
		pre=pre->next;
	}
	if(pre==NULL){
		printf("插入位置不合理!\n");
		return ERROR;
	}
	else
	{
		s=(Node *)malloc(sizeof(Node));//由于s未初始化实际上是个野指针,所以我们需要给他分配一定空间 
		s->data=e;
		s->next=pre->next;
		pre->next=s;
		return OK; 
	}
 } 
 
//单链表删除
//不同于插入位置有n+1个,实际上删除能够合法的位置也就n个
//pre是指向第i-1个结点的指针,这里的i取值是1到n。pre->next为空说明它对应的结点是尾结点,而这是不合法的。 
int DelList(LinkList L, int i, ElemType *e)
{
	if(i<=0)
	{
		return ERROR;
	}
	Node *pre, *s;
	int j=0;
	//第一步是一样的,查找第(i-1)结点 
	while((pre->next!=NULL)&&(j<i-1))
	{
		pre=pre->next;
		j++; 
	 } 
	if(pre->next==NULL){
		printf("插入位置不合理!\n");
		return ERROR;
}
	else{
		s=pre->next;//有初始化,不用malloc了 
		*e=s->data;
		pre->next=s->next;
		free(s);
		return OK; 
	}
}

//例题1-将有序单链表合并成新的有序单链表 
int main()
{
	return 0;
}
举报

相关推荐

0 条评论