数据结构(带头结点的单向非循环链表的相关操作)

链表的概念:物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链实现。
在这里插入图片描述
今天,我们就谈谈单向非循环链表(包括带头结点和不带头结点)
1.单向非循环链表结构定义以及初始化

//结构定义
typedef int Datatype;
typedef struct ListNode {
	Datatype Data;        //数据域
	struct ListNode *Next;   //指针域
}ListNode,*List;
//初始化
//1.不带头结点
void ListInit(List *plist){     
	*plist= NULL;
}
//2.带头结点
void ListInit(List *plist) {      
	*plist = (ListNode *)malloc(sizeof(ListNode));
	(*plist)->Next = NULL;
}

下面我们主要对带头结点的链表进行操作(不带头节点的链表在操作过程中需要对第一个结点进行单独处理,大家可以自行敲击)
2.插入结点

//尾插法
void ListCreate_Tail(List *phead, Datatype x){
	assert(phead != NULL);
	ListNode *p =*phead;
	ListNode *s = (ListNode *)malloc(sizeof(ListNode));
	assert(s != NULL);
	while (p->Next!= NULL) {
		p = p->Next;
	}
	s->Data = x;
	s->Next = NULL;
	p->Next = s;
}
//头插法
void ListCreate_Head(List *phead, Datatype x) {
	assert(phead != NULL);
	ListNode *p = *phead;
	ListNode *s = (ListNode *)malloc(sizeof(ListNode));
	assert(s != NULL);
	s->Data = x;
	s->Next = NULL;
	s->Next = (*phead)->Next;
	(*phead)->Next = s;
}
//按值插入(前提链表为顺序链表)
void ListInsertVal(List *phead, Datatype val) {
	assert(phead != NULL);
	ListNode *p = (*phead)->Next;
	ListNode *q = p->Next;
	while (q != NULL) {
		if (val < (*phead)->Next->Data) {
			ListCreate_Head(phead, val);  //插入元素小于链表所有元素头插法
		}
		else if (val > p->Data&&val<q->Data) {
			ListNode *s = (ListNode *)malloc(sizeof(ListNode));     //中间插入
			s->Data = val;
			s->Next = p->Next;
			p->Next = s;
		}
		p = p->Next;
		q = q->Next;
	}
	ListCreate_Tail(phead, val);      //插入元素大于链表所有元素,采用尾插法
}

3.删除结点

//尾删法
void ListPopBack(List *phead) {
	assert(phead != NULL);
	ListNode *p = *phead;
	if (p->Next == NULL) {
		printf("该链表无元素。无法删除元素!\n");
		return;
	}
	while (p->Next->Next!= NULL) {
		p = p->Next;
	}
	ListNode *s = (ListNode *)malloc(sizeof(ListNode));
	assert(s != NULL);
	s = p->Next;
	p->Next = NULL;
	free(s);
}
//头删法
void ListPopFront(List *phead) {
	assert(phead != NULL);
	ListNode *p = *phead;
	if (p->Next == NULL) {
		printf("该链表无元素。无法删除元素!\n");
		return;
	}
	p = p->Next;
	(*phead)->Next = p->Next;
	free(p);
}
//按值删除
void ListErasebyval(List *phead, Datatype val) {
	assert(phead != NULL);
	ListNode *p =*phead;
	ListNode *pre = NULL;
	while (p->Next!= NULL) {
		pre = p;
		p = p->Next;
		if (val == p->Data) {
			pre->Next = p->Next;
			free(p);
			return;
		}
	}
	printf("无该元素,无法删除!\n");
	return;
}

4查找

//按值查找(返回结点地址)
ListNode *ListFind(ListNode *phead, Datatype val) {
	assert(phead != NULL);
	ListNode *p = phead->Next;
	while (p != NULL) {
		if (p->Data == val) {
			return p;
		}
		p = p->Next;
	}
	return NULL;
}

5.排序

//排序
void ListSort(List *phead) {
	assert(phead != NULL);
	ListNode *tmp = (*phead)->Next, *prev = NULL;
	ListNode *p = (*phead)->Next;
	ListNode *q = p->Next;
	p->Next = NULL;           
	while (q != NULL)
	{
		p = q;                
		q = q->Next;         //摘取第二个结点
		//寻找插入的位置
		while (tmp != NULL && p->Data > tmp->Data)   //元素比该结点元素值大
		{
			prev = tmp;                //保留前驱结点,方便插入
			tmp = tmp->Next;           //向后移动
		}
		if (prev == NULL)           //说明元素值比链表所有元素值都小
		{
			p->Next = (*phead)->Next;        //头插
			(*phead)->Next = p;
		}
		else           //
		{
			p->Next = prev->Next;
			prev->Next = p;
		}
		tmp = (*phead)->Next;   //插入后更新tmp与prev指针
		prev = NULL;
	}
}

6.求表头和表尾元素

//求表头元素
Datatype ListFront(ListNode *phead) {
	assert(phead != NULL);
	ListNode *p = phead->Next;
	if (p != NULL) {
		return p->Data;
	}
	printf("该链表无元素!\n");
	return -1;
}
//求表尾元素
Datatype ListBack(ListNode *phead) {
	assert(phead != NULL);
	ListNode *p = phead->Next;
	if (p == NULL) {
		printf("该链表无元素!\n\n");
		return -1;
	}
	while (p->Next!= NULL) {
		p = p->Next;
	}
	return p->Data;
}

7.清除所有结点以及摧毁元素

void ListClear(List *phead) {
	assert(phead != NULL);
	while ((*phead)->Next != NULL) {
		ListPopFront(phead);             //进行头删法,直到头结点的前驱无元素.
	}
}
//摧毁链表
void ListDestroy(List *phead) {
	assert(phead != NULL);
	ListNode *p = (*phead);
	ListClear(phead);
	free(p);
}

8.转置

//转置
void ListReverse(List *phead) {
	assert(phead != NULL);
	ListNode *p = (*phead)->Next;
	ListNode *q= p->Next;
	p->Next = NULL;
	while (q != NULL) {
		p = q;
		q = q->Next;
		p->Next = (*phead)->Next;
		(*phead)->Next = p;
	}
}

9.遍历

void ShowList(ListNode *phead) {
	assert(phead != NULL);
	ListNode *p =phead->Next;
	while (p != NULL) {
		printf("%d->", p->Data);
		p = p->Next;
	}
	printf("over.\n");
}

上边是关于带头结点的单向非循环链表的一些相关操作,当然链表的结构多种多样,大家有兴趣可以深入了解数据结构。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值