数据结构 线性表

概述

线性表是最常用、最简单的数据结构,其主要的特点就是元素间呈现线性关系,即“一个接一个的排列”。一般采用顺序或链式存储。

定义

一个线性表是 n ( n ≥ 0 ) n(n \geq 0) n(n0)个元素的有限序列,通常表示为 a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,,an,其定义如下:

  1. 存在唯一的“第一个”元素
  2. 存在唯一的“最后一个”元素
  3. 除“第一个”元素外,任一元素都只有一个直接前驱
  4. 除“最后一个”元素外,任一元素都只有一个直接后继

线性表的顺序存储

这是最常用的方式,即用一组地址连续的空间依次存储线性表,在编程中“数组”即是最简单的线性表。

L O C ( a 1 ) LOC(a_1) LOC(a1)表示线性表中第一个元素

在顺序存储结构中,第 i i i个元素 a i a_i ai的存储位置为: L O C ( a i ) = L O C ( a 1 ) + ( i − 1 ) × B y t e s ( 每 个 元 素 所 需 空 间 的 字 节 数 ) LOC(a_i) = LOC(a_1) + (i-1) \times Bytes(每个元素所需空间的字节数) LOC(ai)=LOC(a1)+(i1)×Bytes

可以看出,顺序存储最大的优点即随机存储(Random Access),访问任一位置的元素都可以直接计算出地址,无需额外寻址的过程。

但由于连续的关系,其缺点均体现在删除、插入操作上,这俩操作都需要耗费大量的时间移动元素(以满足顺序存储的特性)。在表长为 n n n的线性表插入元素时,共有 n + 1 n+1 n+1个位置可选,在位置 a 1 a_1 a1插入则需要将整个线性表后移以空出第一位;而在位置 a n + 1 a_{n+1} an+1插入则无需移动任一元素;

P i P_i Pi是在第 i i i个元素前插入一个元素的概率, Q i Q_i Qi是删除第 i i i个元素的概率,可以假定在线性表任何位置上插入、删除都是等概率的,即:
P i = 1 n + 1 , Q i = 1 n P_i = \frac{1}{n+1}, \quad Q_i = \frac{1}{n} Pi=n+11,Qi=n1
每次插入、删除操作需要移动的元素个数期望值 E i n s e r t 、 E d e l e t e E_{insert}、E_{delete} EinsertEdelete如下:

E i n s e r t = ∑ i = 1 n + 1 P i × ( n − i + 1 ) = 1 n + 1 ∑ i = 1 n + 1 ( n − i + 1 ) = n 2 E d e l e t e = ∑ i = 1 n Q i × ( n − i ) = 1 n ∑ i = 1 n ( n − i ) = n − 1 2 \begin{aligned} E_{insert} =& \sum_{i=1}^{n+1} P_i \times (n-i+1) \\ =& \frac{1}{n+1} \sum_{i=1}^{n+1}(n-i+1)\\ =& \frac{n}{2} \\ E_{delete} =& \sum_{i=1}^{n} Q_i \times (n-i)\\ =& \frac{1}{n} \sum_{i=1}^{n} (n-i) \\ =& \frac{n-1}{2} \end{aligned} Einsert===Edelete===i=1n+1Pi×(ni+1)n+11i=1n+1(ni+1)2ni=1nQi×(ni)n1i=1n(ni)2n1

线性表的链式存储

所谓链式,即存储的实际形式宛如链条,并不是物理上的连续,但逻辑上它仍是线性的,编程中“链表”即其实现。

在链式结构中,以结点为单位存储元素,其结构如下:

Linked list node

其中,数据域存储元素,指针域存储当前结点的前驱或后继结点的位置信息。

链式存储的结点并不要求空间是连续的,因此每个结点都需要额外存储结点之间的逻辑关系。

与顺序存储比较,链式的优点主要有:占用空间灵活,无需连续的地址,当需要一个新的结点时再申请;插入和删除无需移动大量元素,只需要将逻辑上相邻的结点的指针域修改即可;但缺点在于没有随机访问能力,由第一个(头结点)往后逐个访问;其次需要额外的空间保存指针信息;

还有特殊的表现形势如双链表、循环链表等,前者主要优势在于提供了倒序访问能力,但缺点显而易见,需要多保存一个指针。后者则在特殊场景中应用方便,符合逻辑。

其具体的逻辑体现如下图:

Linklist structure

图片来自互联网

C语言实现

顺序存储

很早以前学习的时候曾经做过比较完整的基于数组的线性表,但没实现为存储类型无关,供参考,其分为了三个文件:

  • Linear_list.c 函数的实现
  • Linear_list.h 函数头文件,包含函数功能及其说明
  • Linear_list_elemset.h 定义数据类型,用户可在此处定义线性表存储的数据类型
//Linear_list_elemset.h
#ifndef _LINEAR_LIST_ELEMSET_H_
#define _LINEAR_LIST_ELEMSET_H_
#define NAMELEN 20
/* 
	在下面定义数据域,示例:
	typedef int Linear_ElemSet_Data;
			or
	typedef struct {
		int a;
		char b;
		char Name[20];
	} Linear_ElemSet_Data;
*/

typedef struct {
	unsigned short Stu_Id;
	float Stu_Score[3];
	float Stu_Total;
	char Name[NAMELEN];
} Linear_ElemSet_Data;

/* 下方为内部实现需要,不能更改 */
typedef struct {
	Linear_ElemSet_Data *Elem;
	unsigned int List_length;
	unsigned int List_pit;
	unsigned int List_realloc;
	unsigned int List_BufferLen;
} Linear_ElemSet;

typedef Linear_ElemSet LinearList;
typedef Linear_ElemSet_Data LinearListData;
#endif

//Linear_list.h
#ifndef _LINEAR_LIST_H_
#define _LINEAR_LIST_H_
#include "Linear_list_elemset.h"
/*  
	数据结构 2.1 线性表
	建立时间:2015-4-13
	概述:
		线性表(Linear list)是最常用且最简单的一种数据结构。简言之,一个线性表是n个数据元素的有限序列。
	至于每个数据元素的具体含义,在不同的情况下各不相同,它可以是一个数或者是一个符号,也可以是一页
	书,甚至其他更复杂的信息。

	D={ Ai | Ai∈ElemSet, i=1,2,…,n, n≥0 }
	R={ <Ai-1, Ai> | Ai-1, Ai∈D, i=2,…,n }
*/
#define FALSE FALSE
#define TRUE TRUE
typedef enum STATE
{ 
	FALSE, TRUE 
}state;

state LINEAR_InitList( Linear_ElemSet *L , int count );
	//初始化线性表
	//操作结果:构造一个空的线性表L,count为线性表长度阀值(不得低于10),当数据量超出会自动扩展一倍,返回state表示操作是否成功
state LINEAR_DestroyList( Linear_ElemSet *L );
	//销毁线性表
	//初始条件:线性表L已存在
	//操作结果:销毁线性表L,返回state表示操作是否成功
state LINEAR_ClearList( Linear_ElemSet *L );
	//重置(清空)线性表
	//初始条件:线性表L已存在
	//操作结果:将L重置为空表,返回state表示操作是否成功
__inline state LINEAR_ListEmpty( Linear_ElemSet L ) { return L.List_length == 0 ? TRUE: FALSE; }
	//检查线性是否为空
	//初始条件:线性表L已存在
	//操作结果:若L为空表,则返回TRUE,否则返回FALSE
__inline int LINEAR_ListLength( Linear_ElemSet L ) { return L.List_length; }
	//返回线性表长度
	//初始条件:线性表L已存在
	//操作结果:返回L中数据元素个数
state LINEAR_ListEmpty( Linear_ElemSet L );
	//检查线性是否为空
	//初始条件:线性表L已存在
	//操作结果:若L为空表,则返回TRUE,否则返回FALSE
int LINEAR_ListLength( Linear_ElemSet L );
	//返回线性表长度
	//初始条件:线性表L已存在
	//操作结果:返回L中数据元素个数
state LINEAR_GetElem( Linear_ElemSet L, int i, Linear_ElemSet_Data *e );
	//获取元素
	//初始条件:线性表L已存在,1≤i≤ListLength(L)
	//操作结果:用e返回L中第i个数据元素的值。并返回state表示操作是否成功
int LINEAR_LocateElem( Linear_ElemSet L, Linear_ElemSet_Data e, int (*compare)(Linear_ElemSet_Data, Linear_ElemSet_Data) );
	//定位元素
	//初始条件:线性表L已存在,compare()是数据元素的判定函数(返回0为FALSE,其余为TRUE)
	//操作结果:返回L中第1个与e满足关系compare()的数据元素的位序,若这样的数据元素不存在,则返回值为0
state LINEAR_PriorElem( Linear_ElemSet L, int i, Linear_ElemSet_Data *pre_e );
	//返回目标元素的前一个元素
	//初始条件:线性表L已存在,2≤i≤ListLength(L)
	//操作结果:用pre_e返回L中第i个数据元素的前一个元素的值。并返回state表示操作是否成功
state LINEAR_NextElem( Linear_ElemSet L, int i, Linear_ElemSet_Data *next_e );
	//返回目标元素的后一个元素
	//初始条件:线性表L已存在,1≤i≤( ListLength(L) - 1 )
	//操作结果:用next_e返回L中第i个数据元素的后一个元素的值,并返回state表示操作是否成功
int LINEAR_ListAddElem( Linear_ElemSet *L, Linear_ElemSet_Data e );
	//为线性表添加一个元素
	//初始条件:线性表L已存在
	//操作结果:在L中的尾部插入一个新的数据元素e,L的长度加1。并返回添加后线性表长度
state LINEAR_ListInsert( Linear_ElemSet *L, int i, Linear_ElemSet_Data e );
	//为线性表插入一个元素
	//初始条件:线性表L已存在,1≤i≤( ListLength(L) +1 )
	//操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1。并返回state表示操作是否成功
state LINEAR_ListDelete( Linear_ElemSet *L, int i, Linear_ElemSet_Data *e );
	//为线性表删除一个元素
	//初始条件:线性表L已存在且非空,1≤i≤ListLength(L)
	//操作结果:删除L的第i个元素,并用e返回被删除元素的值,L的长度减1。并返回state表示操作是否成功
state LINEAR_ListElemCover( Linear_ElemSet *L, int i, Linear_ElemSet_Data *e );
	//对线性表一个指定元素执行覆盖
	//初始条件:线性表已存在且非空,1≤i≤ListLength(L)
	//操作结果:使用e覆盖L的第i个元素,返回state表示操作是否成功
state LINEAR_ListTraverse( Linear_ElemSet L, int (*visit)(Linear_ElemSet_Data) );
	//历遍线性表
	//初始条件:线性表L已存在且非空
	//操作结果:依次对线性表里的每一个数据元素执行visit()函数,一旦visit返回0(FALSE),则操作失败。并返回state表示操作是否成功
#endif

//Linear_list.c
#include "Linear_list.h"
#include <malloc.h>
#include <stdio.h>

static state LINEAR_ReallocList( Linear_ElemSet *L )
{
	Linear_ElemSet_Data *pNew = ( Linear_ElemSet_Data *) realloc( (*L).Elem, sizeof(Linear_ElemSet_Data) * ( (*L).List_pit + (*L).List_pit * (*L).List_realloc ) );
	if( pNew == NULL )
		return FALSE;

	(*L).Elem = pNew;
	(*L).List_BufferLen += (*L).List_pit;
	(*L).List_realloc++;
	return TRUE;
}

state LINEAR_InitList( Linear_ElemSet *L , int count )
{
	(*L).List_length = 0;
	(*L).List_pit = count;
	(*L).List_realloc = 1;
	(*L).List_BufferLen = count;

	if( count < 10 )
	{
		fprintf( stderr, "LINEAR_InitList Function Error\n" );
		fprintf( stderr, "the List Pit can't lower than 10\n" );
		return FALSE;
	}

	if( ( (*L).Elem = ( Linear_ElemSet_Data *) malloc( sizeof(Linear_ElemSet_Data) * (*L).List_pit ) ) == NULL )
	{
		fprintf( stderr, "LINEAR_InitList Function Error\n" );
		fprintf( stderr, "Can't allocate Memory!\n" );
		return FALSE;
	}
	return TRUE;
}
	//初始化线性表
	//操作结果:构造一个空的线性表L,count为线性表长度阀值(不得低于10),当数据量超出会自动扩展一倍,返回state表示操作是否成功
state LINEAR_DestroyList( Linear_ElemSet *L )
{
	if( (*L).Elem == NULL )
	{
		fprintf( stderr, "LINEAR_DestroyList Function Error\n" );
		fprintf( stderr, "This Linear has been free!\n" );
		return FALSE;
	}
	free( (*L).Elem );
	(*L).List_length = 0;
	return TRUE;
}
	//销毁线性表
	//初始条件:线性表L已存在
	//操作结果:销毁线性表L,返回state表示操作是否成功
state LINEAR_ClearList( Linear_ElemSet *L )
{
	if( LINEAR_ListEmpty(*L) )
	{
		fprintf( stderr, "LINEAR_ClearList Function Error\n" );
		fprintf( stderr, "The Linear is emtpy!\n" );
		return FALSE;
	}
	(*L).List_length = 0;
	return TRUE;
}
	//重置(清空)线性表
	//初始条件:线性表L已存在
	//操作结果:将L重置为空表,返回state表示操作是否成功
state LINEAR_GetElem( Linear_ElemSet L, int i, Linear_ElemSet_Data *e )
{
	if( LINEAR_ListEmpty(L) || i > LINEAR_ListLength(L) || i <= 0 )
	{
		fprintf( stderr, "LINEAR_GetElem Function Error\n" );
		fprintf( stderr, "Out of bound! List length is %d, i is %d\n", LINEAR_ListLength(L), i );
		return FALSE;
	}
	*e = L.Elem[i-1];
	return TRUE;
}
	//获取元素
	//初始条件:线性表L已存在,1≤i≤ListLength(L)
	//操作结果:用e返回L中第i个数据元素的值。并返回state表示操作是否成功
int LINEAR_LocateElem( Linear_ElemSet L, Linear_ElemSet_Data e, int (*compare)(Linear_ElemSet_Data, Linear_ElemSet_Data) )
{
	int i;

	if( LINEAR_ListEmpty(L) )
	{
		fprintf( stderr, "LINEAR_LocateElem Function Error\n" );
		fprintf( stderr, "The Linear is empty!\n" );
		return FALSE;
	}

	for( i = 0; i < LINEAR_ListLength(L); i++ )
	{
		if( compare( L.Elem[i], e ) != FALSE )
			return i+1;
	}
	return 0;
}
	//定位元素
	//初始条件:线性表L已存在,compare()是数据元素的判定函数(返回0为FALSE,其余为TRUE)
	//操作结果:返回L中第1个与e满足关系compare()的数据元素的位序,若这样的数据元素不存在,则返回值为0
state LINEAR_PriorElem( Linear_ElemSet L, int i, Linear_ElemSet_Data *pre_e )
{
	if( LINEAR_ListEmpty(L) || i > LINEAR_ListLength(L) || i <= 1 ) 
	{
		fprintf( stderr, "LINEAR_PriorElem Function Error\n" );
		fprintf( stderr, "Out of bound! List length is %d, i is %d\n", LINEAR_ListLength(L), i );
		return FALSE;
	}

	*pre_e = L.Elem[i-2];
	return TRUE;
}
	//返回目标元素的前一个元素
	//初始条件:线性表L已存在,2≤i≤ListLength(L)
	//操作结果:用pre_e返回L中第i个数据元素的前一个元素的值。并返回state表示操作是否成功
state LINEAR_NextElem( Linear_ElemSet L, int i, Linear_ElemSet_Data *next_e )
{
	if( LINEAR_ListEmpty(L) || i >= LINEAR_ListLength(L) || i <= 0 ) 
	{
		fprintf( stderr, "LINEAR_NextElem Function Error\n" );
		fprintf( stderr, "Out of bound! List length is %d, i is %d\n", LINEAR_ListLength(L), i );
		return FALSE;
	}

	*next_e = L.Elem[i];
	return TRUE;
}
	//返回目标元素的后一个元素
	//初始条件:线性表L已存在,1≤i≤( ListLength(L) - 1 )
	//操作结果:用next_e返回L中第i个数据元素的后一个元素的值,并返回state表示操作是否成功
state LINEAR_ListInsert( Linear_ElemSet *L, int i, Linear_ElemSet_Data e )
{
	int j;
	if( LINEAR_ListLength(*L) >= (*L).List_BufferLen )
	{
		if( LINEAR_ReallocList(L) == FALSE )
		{
			fprintf( stderr, "LINEAR_ListInsert Function Error\n" );
			fprintf( stderr, "Can't realloc the memory! list length is %d, list buffer len is %d\n", LINEAR_ListLength(*L), (*L).List_BufferLen );
			fprintf( stderr, "Cancle the Insert opeartion!\n" );
			return FALSE;
		}
	}
	if( LINEAR_ListEmpty(*L) || i > LINEAR_ListLength(*L) || i<= 0 )
	{
		fprintf( stderr, "LINEAR_ListInsert Function Error\n" );
		fprintf( stderr, "Can't insert in that postion! Listlength is %d, i is %d\n", LINEAR_ListLength(*L), i );
		return FALSE;
	}

	for( j=LINEAR_ListLength(*L); j>=i; j-- )
	{
		(*L).Elem[j] = (*L).Elem[j-1];
	}
	(*L).Elem[i-1] = e;
	(*L).List_length++;
	return TRUE;
}
	//为线性表插入一个元素
	//初始条件:线性表L已存在,1≤i≤( ListLength(L) +1 )
	//操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1。并返回state表示操作是否成功
int LINEAR_ListAddElem( Linear_ElemSet *L, Linear_ElemSet_Data e )
{
	if( LINEAR_ListLength(*L) >= (*L).List_BufferLen )
	{
		if( LINEAR_ReallocList(L) == FALSE )
		{
			fprintf( stderr, "LINEAR_ListAddElem Function Error\n" );
			fprintf( stderr, "Can't realloc the memory! list length is %d, list buffer len is %d\n", LINEAR_ListLength(*L), (*L).List_BufferLen );
			fprintf( stderr, "Cancle the Add opeartion!\n" );
			return LINEAR_ListLength(*L);
		}
	}
	(*L).Elem[LINEAR_ListLength(*L)] = e;
	++(*L).List_length;
	return LINEAR_ListLength(*L);
}
	//为线性表添加一个元素
	//初始条件:线性表L已存在
	//操作结果:在L中的尾部插入一个新的数据元素e,L的长度加1。并返回state表示操作是否成功
state LINEAR_ListDelete( Linear_ElemSet *L, int i, Linear_ElemSet_Data *e )
{
	int j;
	if( LINEAR_ListEmpty(*L) || i > LINEAR_ListLength(*L) || i<= 0 )
	{
		fprintf( stderr, "LINEAR_ListDelete Function Error\n" );
		fprintf( stderr, "Can't delete in that postion! Listlength is %d, i is %d\n", LINEAR_ListLength(*L), i );
		return FALSE;
	}

	*e = (*L).Elem[i-1];
	for( j=i; j<LINEAR_ListLength(*L); j++ )
	{
		(*L).Elem[j-1] = (*L).Elem[j];
	}
	(*L).List_length--;
	return TRUE;
}
	//为线性表删除一个元素
	//初始条件:线性表L已存在且非空,1≤i≤ListLength(L)
	//操作结果:删除L的第i个元素,并用e返回被删除元素的值,L的长度减1。并返回state表示操作是否成功
state LINEAR_ListElemCover( Linear_ElemSet *L, int i, Linear_ElemSet_Data *e )
{
	if( LINEAR_ListEmpty(*L) || i > LINEAR_ListLength(*L) || i<= 0 )
	{
		fprintf( stderr, "LINEAR_ListElemCover Function Error\n" );
		fprintf( stderr, "Can't Cover in that postion! Listlength is %d, i is %d\n", LINEAR_ListLength(*L), i );
		return FALSE;
	}

	(*L).Elem[i] = *e;
	return TRUE;
}
	//对线性表一个指定元素执行覆盖
	//初始条件:线性表已存在且非空,1≤i≤ListLength(L)
	//操作结果:使用e覆盖L的第i个元素,返回state表示操作是否成功
state LINEAR_ListTraverse( Linear_ElemSet L, int (*visit)(Linear_ElemSet_Data) )
{
	int i;

	if( LINEAR_ListEmpty(L) )
	{
		fprintf( stderr, "LINEAR_ListTraverse Function Error\n" );
		fprintf( stderr, "List is empty!\n" );
		return FALSE;
	}

	for( i=0; i<LINEAR_ListLength(L); i++ )
	{
		if( visit(L.Elem[i]) == FALSE )
		{
			fprintf( stderr, "Visit Error in %d element!\n", i+1 );
			return FALSE;
		}
	}

	return TRUE;
}
	//历遍线性表
	//初始条件:线性表L已存在且非空
	//操作结果:依次对线性表里的每一个数据元素执行visit()函数,一旦visit返回0(FALSE),则操作失败。并返回state表示操作是否成功

链式存储

采用的简单单链表及无头结点实现,有两个文件。实际上通过设计一个头结点会使得代码更简单易懂,并且对链表的维护更容易。

//Link_list.h
#ifndef _LINK_LIST_H_
#define _LINK_LIST_H_
#include <stdio.h>
#include <malloc.h>

typedef struct {
	int data;
	struct LLNode *Next;
}LLNode, *LLHead;

typedef int DataType;
/*
初始化LLHead。
*/
void LL_Initialize(LLHead *p);

/*
插入元素:将elem插入到pos的位置(0为第一位)
初始条件:p已初始化,pos为有效位置(≥0,若大于链表长度不论为多少默认为最后)
操作结果:成功返回1,否则返回0
*/
int LL_Insert(LLHead *p, int pos, DataType elem);

/*
删除元素:删除pos位置的元素
初始条件:p已初始化,pos为有效位置(≥0且≤链表长度-1)
操作结果:成功返回1,否则返回0
*/
int LL_Delete(LLHead *p, int pos);

/*
查找元素:查找elem元素的位置
初始条件:p已初始化
操作结果:若元素存在于链表中,返回位置pos;否则返回-1
*/
int LL_Find(LLHead p, DataType elem);

/*
查找元素:查找位于pos的元素
初始条件:p已初始化,pos为有效位置(≥0且≤链表长度-1)
操作结果:若pos有效,将修改outElem中内容为该位置元素并返回1;否则返回0。
*/
int LL_FindAt(LLHead p, int pos, DataType *outElem);

#endif
//Link_list.c
#include "Link_list.h"

static LLNode* NewNode(DataType dat, LLNode *next)
{
	LLNode *p = malloc(sizeof(LLNode));
	if (p == NULL)
	{
		fprintf(stderr, "Can't allocate memory!");
		return NULL;
	}
	p->data = dat;
	p->Next = next;

	return p;
}

void LL_Initialize(LLHead * p)
{
	*p = NULL;
}

//由于该链表不存在单独的头结点,LLHead是指向头结点的指针变量,插入或删除有时候需要修改头指针变量,因此参数为LLHead *。
int LL_Insert(LLHead * p, int pos, DataType elem)
{
	if (pos < 0)
		return 0;

	LLNode *pcur = *p;
	LLNode *prev = NULL;	//保留前继指针方便修改

	if (pcur == NULL)	//当p为NULL意味着是一个新的链表,直接插入并修改头指针
		*p = NewNode(elem, NULL);
	else if (pos == 0) //当pos为0时意味着插入到链表头,同样直接插入并修改头指针
		*p = NewNode(elem, pcur);
	else
	{
		while (pcur != NULL && pos-- >= 0)	//循环完毕后要么已经到了链表的尾部,要么到达了pos的位置
		{
			prev = pcur;
			pcur = pcur->Next;
		}
		prev->Next = NewNode(elem, pcur);
	}

	return 1;
}

int LL_Delete(LLHead * p, int pos)
{
	if (*p == NULL)
	{
		fprintf(stderr, "Empty List!");
		return 0;
	}

	if (pos == 0) //如若删除链表第一个,则需要修改头指针
	{
		*p = (*p)->Next;
		return 1;
	}

	LLNode *pcur = *p;
	LLNode *prev = NULL;

	while (pcur != NULL && pos-- >= 0)
	{
		prev = pcur;
		pcur = pcur->Next;
	}

	if (pos >= 0) //如果pos仍然≥0,则说明pos长度大于链表最大长度。
	{
		fprintf(stderr, "Out of Bound!");
		return 0;
	}

	//删除第n位链表结点,实际上就是使第n-1位结点指向n+1位结点。
	prev->Next = pcur->Next;
	free(pcur);
	return 1;
}

int LL_Find(LLHead p, DataType elem)
{
	if (p == NULL)
	{
		fprintf(stderr, "Empty List!");
		return 0;
	}

	int pos = 0;

	while (p != NULL)
	{
		if (p->data == elem)
			return pos;

		pos++;
		p = p->Next;
	}
	//循环结束如果尚未返回证明链表中不存在该元素

	return -1;
}

int LL_FindAt(LLHead p, int pos, DataType *outElem)
{
	if (p == NULL)
	{
		fprintf(stderr, "Empty list!");
		return 0;
	}
	if (outElem == NULL)
	{
		fprintf(stderr, "outElem is NULL!");
		return 0;
	}
	if (pos < 0)
	{
		fprintf(stderr, "Out of Bound!");
		return 0;
	}

	while (p != NULL && pos-- > 0)
		p = p->Next;

	if (pos >= 0)
	{
		fprintf(stderr, "Out of Bound!");
		return 0;
	}
	
	*outElem = p->data;
	return 1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值