数据结构——链表——无头单向非循环链表

数据结构——链表——无头单向非循环链表

    • 无头单向非循环链表
      • 函数接口声明
      • 函数接口实现

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链
接次序实现的。实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  1. 单向、双向
  2. 带头、不带头
  3. 循环、非循环

本文学习总结最常用两种结构:

  1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。
  2. 带头双向循环链表:结构复杂,一般用于单独存储数据。

无头单向非循环链表

定义无头单向非循环链表节点:

typedef struct SListNode
{
     
	ElemType data;
	struct SListNode *next;
}SListNode;

定义无头单向非循环链表结构:

typedef struct SList
{
     
	SListNode *head; //结构体内为一个单链表节点类型的指针
}SList;

函数接口声明

void SListInit(SList *plist);
void SListPushBack(SList *plist,ElemType x);
static SListNode* _Buynode(ElemType x);  //申请节点
void SListShow(SList *plist);
void SListPushFront(SList *plist, ElemType x);
void SListPopBack(SList *plist);
void SListDestroy(SList *plist);
void SListPopFront(SList *plist);
size_t SListLength(SList *plist);
void SListClear(SList *plist);
SListNode *SeqListFind(SList *plist,ElemType key);
void SListDeleteByVal(SList *plist, ElemType key);
void SListReverse(SList *plist);
void SListInsertByVal(SList *plist, ElemType x);
void SListSort(SList *plist);

函数接口实现

初始化链表:

void SListInit(SList *plist)
{
     
	plist->head = NULL;
}

结点的空间申请:

static SListNode* _Buynode(ElemType x)
{
     
SListNode *s = (SListNode*)malloc(sizeof(SListNode));
	assert(s!=NULL);
	s->data = x;
	s->next = NULL;
	return s;
}

链表尾插:

void SListPushBack(SList *plist, ElemType x)
{
     
	assert(plist!=NULL);//断言

	SListNode *s = _Buynode(x);//结点申请
	//如果插入的结点为第一个结点
	if (plist->head==NULL)
	{
     
		plist->head = s;
	}

	SListNode *p = plist->head;
	while (plist->head != NULL)
		p = p->next;
	p->next = s;
}

显示链表:

void SListShow(SList *plist)
{
     
	SListNode *p = plist->head;
	while (p!=NULL)
	{
     
		printf("%d-->",p->data);
		p = p->next;
	}
	printf("Over.\n");
}

单链表头部插入:

void SListPushFront(SList *plist, ElemType x)
{
     
	assert(plist!=NULL);

	SListNode *s = _Buynode(x);

	s->next = plist->head;
	plist->head = s;
}

单链表尾部删除:

void SListPopBack(SList *plist)
{
     
	assert(plist!=NULL);//断言
	SListNode *p;
	if (plist->head == NULL)//链表为空时;
		return;
	 p = plist->head;

	//当链表只有一个结点时
	if (p->next == NULL)
	{
     
		free(p);
		plist->head = NULL;
		return;
	}
//至少两个结点时
	while (p->next->next != NULL)
		p = p->next;
	free(p->next);
	p->next = NULL;
}

单链表的清除:

void SListClear(SList *plist)
{
     
	assert(plist != NULL);
	SListNode *p = plist->head;
	while (p != NULL)
	{
     
		plist->head = p->next;
		free(p);
		p = plist->head;
	}
}

单链表的摧毁:

void SListDestroy(SList *plist)
{
     
	SListClear(plist);
	plist->head = NULL;
}

单链表头部删除:

void SListPopFront(SList *plist)
{
     
	assert(plist!=NULL);
	SListNode *p = plist->head;

	if (plist->head == NULL)
		return;

	plist->head = p->next;
	free(p);
}

单链表长度:

size_t SListLength(SList *plist)
{
     
	assert(plist!=NULL);
	size_t len = 0;
	SListNode *p = plist->head;

	while (p != NULL)
	{
     
		len++;
		p = p->next;
	}
	return len;
}

单链表按值查找:

SListNode *SeqListFind(SList *plist, ElemType key)
{
     
	assert(plist != NULL);
	SListNode *p = plist->head;
	while (p != NULL && p->data != key)
		p = p->next;
	return p;
}

单链表按值删除:

void SListDeleteByVal(SList *plist, ElemType key)
{
     
	assert(plist!=NULL);
	SListNode *prev = NULL;
	SListNode *p = SeqListFind(plist,key);

	if (p == NULL)
	{
     
		printf("要删除的结点不存在.\n");
		return;
	}
	//判断是否找到的是第一个结点(特殊处理)
	if (p == plist->head)
		plist->head = p->next;
	else
	{
     
		prev = plist->head;
		while (prev->next != p)
			prev = prev->next;
		//删除结点
		prev->next = p->next;
	}
	free(p);
}

单链表转置操作:

void SListReverse(SList *plist)
{
     
	assert(plist != NULL);
	SListNode *p = plist->head->next;
	SListNode *q;
	if (p->next == NULL)
		return;
	//断开第一个结点
	plist->head->next = NULL;
	while (p != NULL)
	{
     
		q = p->next;
		p->next = plist->head;
		plist->head = p;
	}
}

单链表按值插入:

void SListInsertByVal(SList *plist, ElemType x)
{
     
	assert(plist!=NULL);
	SListNode *prev = NULL;
	SListNode *p = plist->head;
	SListNode *s = _Buynode(x);

	//判断要插入的位置
	while (p!=NULL && x>p->data)
	{
     
		prev = p;
		p = p->next;
	}
	if (prev == NULL)//需进行头插
	{
     
		s->next = p;
		plist->head = s;
	}
	else
	{
     
		s->next = prev->next;
		prev->next = s;
	}
}

单链表排序:

void SListSort(SList *plist)
{
     
	assert(plist != NULL);
	SListNode *p = plist->head->next;
	SListNode *q, *t, *prev = NULL;

	plist->head->next = NULL;//断开链表
	t = plist->head;
	while (p != NULL)
	{
     
		q = p->next;
		//把p结点摘除进行按值插入,升序
		while (t!=NULL && p->data>t->data)
		{
     
			prev = t;
			t = t->next;
		}
		if (prev==NULL)
		{
     
			prev->next = plist->head;
			plist->head = p;
		}
		else
		{
     
			p->next = prev->next;
			prev->next = p;
		}
		p = q;
		t = plist->head;
	}
}

下一次将对带头双向循环链表的基本操作进行叙述。

你可能感兴趣的:(c++)