线性表——数据结构之一

1.什么是线性表?

线性表是一个线性结构,它是一个含有n≥0个结点的有限序列,对于其中的结点,有且仅有一个开始结点没有前驱但有一个后继结点,有且仅有一个终端结点没有后继但有一个前驱结点,其它的结点都有且仅有一个前驱和一个后继结点。一般地,一个线性表可以表示成一个线性序列:a0,a1...an其中a1是开始结点,an是终端结点

2.线性表的存储结构有哪些?

(1)顺序存储结构

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的地址连续的存储单元依次存储线性表的数据元素。


(2)链式存储定义

为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。


3.顺序表的常见操作有哪些?

线性表的操作主要包括:

(1)创建线性表

(2)清空线性表

(3)销毁线性表

(4)删除线性表元素

(5)插入元素

(6)获取第i个元素,0≤i<n

(7)计算表的长度n

4.线性表顺序存储结构的实现

1).建立头文件seqlist.h,将数据类型线性表声明为void,实现对数据的封装

#ifndef _SEQLIST_H_
#define _SEQLIST_H_
//申明为void,实现数据的封装,之后再main函数的使用过程中,
//只能通过提供的线性表操作函数来修改线性表长度,插入数据等操作
//因为线性表为void类型,同时也不用关心线性表的具体类型
typedef void SeqList;
typedef void SeqListNode;

SeqList* SeqList_Create(int capacity);

void SeqList_Destroy(SeqList* list);

void SeqList_Clear(SeqList* list);

int SeqList_Length(SeqList* list);

int SeqList_Capacity(SeqList* list);

int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

SeqListNode* SeqList_Get(SeqList* list, int pos);

SeqListNode* SeqList_Delete(SeqList* list, int pos);

#endif
2).在seqlist.c中具体实现线性表的操作
#include 
    
    
     
     
#include 
     
     
      
      
#include "Seqlist.h"
/*定义节点存储的数据类型,为地址*/ 
typedef unsigned int TSeqListNode;

typedef struct _tag_SeqList
{
    int capacity;	//线性表最大长度
    int length;		//线性表当前长度
    TSeqListNode* node;		//用来存储线性表的元素地址
} TSeqList;

/*Fuction:1.顺序存储结构创建一个线性表
 *@para capacity the maxsize of Seqlist 
 */
SeqList* SeqList_Create(int capacity)//O(1)
{
	int ret = 0;
	ret = (capacity != 0);
	TSeqList* seqlist = NULL;
	
	if(ret)
	{
		seqlist = (TSeqList*)malloc(sizeof(TSeqList)+capacity*sizeof(TSeqListNode));
		ret = ret && (seqlist != NULL);
		if(ret)
		{
			seqlist -> capacity = capacity;
			seqlist -> length = 0;
			seqlist -> node = (TSeqListNode*)(seqlist+1);
		}
		else
		{
			free(seqlist);
			seqlist = NULL;	
		}
	}
	else
	{
		return NULL;
	}
	
	return seqlist;
}

void SeqList_Destroy(SeqList* list)//O(1)
{
	int ret = 0;
	TSeqList* seqlist = (TSeqList*)list;
	 
	ret = (seqlist != NULL);
	if(ret)
	{
		free(seqlist);
		seqlist = NULL;
	}
}

void SeqList_Clear(SeqList* list)//O(1)
{
	int ret = 0;
	TSeqList* seqlist = (TSeqList*)list;
	 
	ret = (seqlist != NULL);
	if(ret)
	{
		seqlist ->length = 0;
	}
	
}

int SeqList_Length(SeqList* list)//O(1)
{

	int ret = 0;
	TSeqList* seqlist = (TSeqList*)list;
	 
	ret = (seqlist != NULL);
	if(ret)
	{
		ret = seqlist ->length;
	}

    return ret;
    
}

int SeqList_Capacity(SeqList* list)//O(1)
{
	int ret = 0;
	TSeqList* seqlist = (TSeqList*)list;
	 
	ret = (seqlist != NULL);
	if(ret)
	{
		seqlist -> capacity;
	}	
}

/*插入元素的时候明白一点,顺序存储结构的线性表其实就是一个数组*/
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos)//O(n)
{

	int ret = 0;
	int i = 0; 
	TSeqList* seqlist = (TSeqList*)list;
	ret = (seqlist != NULL) && (node != NULL) && (pos >= 0) && (seqlist->length < seqlist->capacity);
	if(ret)
	{

		if(pos > seqlist->length)
		{
			pos = seqlist->length;
		}
		
		i = seqlist->length - 1;
		
		for(i ;i >= pos;i--)
		{
			seqlist->node[i+1] = seqlist->node[i];
		}
		
		seqlist->node[pos] = (TSeqListNode)node;
		
		seqlist->length++;
		
	}

	return ret;

}
/*获取一个元素*/
SeqListNode* SeqList_Get(SeqList* list, int pos)//O(1)
{
	int ret = 0;
	TSeqList* seqlist = (TSeqList*)list;	
	ret = (seqlist != NULL) && (0 <= pos);
	if(ret)
	{
		if(pos >= seqlist->length)
		{
			pos = seqlist->length -1;	
		}
		ret = (SeqListNode*)seqlist->node[pos]; 
	}
	return ret;
}
/*删除一个元素*/
SeqListNode* SeqList_Delete(SeqList* list, int pos)//O(n)
{
	int ret = 0;
	int i = 0; 
	
	TSeqList* seqlist = (TSeqList*)list;
	SeqListNode* node = NULL;
	ret = (seqlist != NULL) && (pos >= 0) && (seqlist->length > 0);
	
	if(ret)
	{
		
		if(pos > seqlist->length)
		{
			pos = seqlist->length -1;
		}
		
		i = pos;
		
		node = (SeqListNode*)seqlist->node[pos];
		
		for(i ;i < seqlist->length - 1;i++)
		{
			seqlist->node[i] = seqlist->node[i+1];
		}
		
		seqlist->length--; 
	}
	
	return node;	
}


     
     
    
    
3).测试代码
#include 
    
    
     
     
#include "Seqlist.h"

int main()
{
    SeqList* list = SeqList_Create(5);
    
	char i[] = "a";
	char j[] = "b";
	char k[] = "c";
	char x[] = "d";
	char y[] = "e";
	char z[] = "f";
    int index = 0;

    SeqList_Insert(list, &i, 0);
    
    SeqList_Insert(list, &j, 7);
    SeqList_Insert(list, &k, 7);
    SeqList_Insert(list, &x, 7);
    SeqList_Insert(list, &y, 7);
    SeqList_Insert(list, &z, 7);
	printf("length = %d\n",SeqList_Length(list));
	
	

    for(index=0; index
     
     
      
       0 )
    {
        char* p = (char*)SeqList_Delete(list, 0);
        
        printf("%s\n", p);
    }

    SeqList_Destroy(list);
    
	return 0; 
}

     
     
    
    
4).结果


5.线性表链式存储结构的实现
1)将对链表操作函数的声明放在slist.h中
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
//此处定义链表的类型为void,方便后续使用可以接受任何类型的数据 
typedef void LinkList;
typedef struct _tag_LinkListNode LinkListNode;
//链表指针域 
struct _tag_LinkListNode
{
    LinkListNode* next;
};

LinkList* LinkList_Create();

void LinkList_Destroy(LinkList* list);

void LinkList_Clear(LinkList* list);

int LinkList_Length(LinkList* list);

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);

LinkListNode* LinkList_Get(LinkList* list, int pos);

LinkListNode* LinkList_Delete(LinkList* list, int pos);

#endif

2)将对链表操作函数的实现放入slist.c中,实现如下
/*******************************************************************************
 *Fuction:实现一个可复用的链表,整个链表的操作都是基于链表节点的地址,
 *		  因此获取链表元素以及插入元素到链表都是对链表节点的地址的操作,
 *		  并没有对链表中所存储的数据进行操作,好处就是链表的数据域可扩展行比较好,
 *		  可以添加任意数据到数据域
 *Description:创建一个链表,返回链表地址
 *parameter:
 *******************************************************************************/

#include <stdio.h>
#include <malloc.h>
#include "LinkList.h"
/****************************************************************
 *Description:头结点结构体
 *Variable:header为头结点的地址,length保存链表的长度,注意两个变量的顺序不能调换
 *因为第一个变量的地址就是结构体变量的地址
 ***************************************************************/
typedef struct _tag_LinkList
{
    LinkListNode header;
    int length;
}TLinkList;

/****************************************************************
 *Description:创建一个链表,返回链表地址
 *parameter:
 ***************************************************************/
LinkList* LinkList_Create() // O(1)
{
	TLinkList* slist = NULL;
	slist = (TLinkList*)malloc(sizeof(TLinkList));
	if(NULL != slist)
	{
		slist->header.next = NULL;
		slist -> length = 0;	
	}
	
	return slist;
}
/****************************************************************
 *Description:销毁一个链表,返回链表地址
 *parameter:
 ***************************************************************/
void LinkList_Destroy(LinkList* list) // O(1)
{
	TLinkList* slist = (TLinkList*)list;
	if(NULL != slist)
	{
		free(slist);
		slist = NULL;
	}
}
/****************************************************************
 *Description:清空一个链表
 *parameter:
 ***************************************************************/
void LinkList_Clear(LinkList* list) // O(1)
{
	TLinkList* slist = (TLinkList*)list;
	if(NULL != slist)
	{
		slist->header.next = NULL;
		slist -> length = 0;
	}
}

/****************************************************************
 *Description:返回链表长度
 *parameter:
 ***************************************************************/
int LinkList_Length(LinkList* list) // O(1)
{
	int ret = -1;
	TLinkList* slist = NULL;
	slist = (TLinkList*)list;
	if(NULL != slist)
	{
		ret = slist -> length;
	}
	return ret;
}

/****************************************************************
 *Description:插入一个节点到链表,node为一个节点的地址
 *parameter:
 *varibale:pre_node保存插入节点的前一个指针,cur_node要插入节点的位置 
 ***************************************************************/
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) // O(n)
{
	int i = 0;
	TLinkList* slist = (TLinkList*)list;
	LinkListNode* pre_node = (LinkListNode*)slist;

	int ret = (NULL!=list) && (NULL != node) && (pos >= 0);
	
	if(ret)
	{
		if(pos >= slist->length)
		{
			pos = slist -> length;	
		}

		for(i=0; i<pos; i++)
		{
			pre_node = pre_node -> next;	
		} 
		node -> next = pre_node -> next;
		pre_node -> next = node;	
		
		slist -> length++;
	}
	
	return ret;	
}
/****************************************************************
 *Description:获取链表一个节点的地址,返回的是一个节点的地址
 *parameter:
 ***************************************************************/
LinkListNode* LinkList_Get(LinkList* list, int pos) // O(n)
{
	int i = 0;
	TLinkList* slist = (TLinkList*)list;
	LinkListNode* cur_node = (LinkListNode*)slist;
	
	if((NULL!=slist) && (pos >= 0) &&(slist -> length > 0))
	{
		if(pos >= slist->length)
		{
			pos = slist -> length - 1;	
		}
		
		for(i=0; i<=pos; i++)
		{
			cur_node = cur_node -> next;
		}
	}
	
	return cur_node;
		
}

LinkListNode* LinkList_Delete(LinkList* list, int pos) // O(n)
{
	int i = 0;
	TLinkList* slist = (TLinkList*)list;
	LinkListNode* pre_node = (LinkListNode*)slist;
	LinkListNode* cur_node = NULL;
	
	if((NULL!=slist) && (pos >= 0) &&(slist -> length > 0))
	{
		if(pos >= slist->length)
		{
			pos = slist -> length - 1;	
		}

		for(i=0;i<pos;i++)
		{
			pre_node = pre_node -> next;	
		}
		
		cur_node = pre_node -> next;
		pre_node -> next = cur_node-> next; 

		slist -> length--;
	}
	
	return cur_node;	
}

3)测试代码

#include <stdio.h>
#include <stdlib.h>
#include "LinkList.h"

struct Value
{
	LinkListNode header;
    int v;
};

int main(int argc, char *argv[]) 
{
    int i = 0;
    LinkList* list = LinkList_Create();
    
    struct Value v1;
    struct Value v2;
    struct Value v3;
    struct Value v4;
    struct Value v5;
    
    v1.v = 1;
    v2.v = 2;
    v3.v = 3;
    v4.v = 4;
    v5.v = 5;
    
    LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list));
    
    LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list));
    LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list));
    LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list));
    LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list));
    
    printf("LinkList_Length(list) = %d\n",LinkList_Length(list));

    for(i=0; i<LinkList_Length(list); i++)
    {
        struct Value* pv = (struct Value*)LinkList_Get(list, i);
        
        printf("%d\n", pv->v);
    }
    
    while( LinkList_Length(list) > 0 )
    {
        struct Value* pv = (struct Value*)LinkList_Delete(list, 0);
        
        printf("%d\n", pv->v);
    }
    
    LinkList_Destroy(list);
    return 0;
}
4)运行结果







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include"stdio.h" #include<malloc.h> typedef char ElemType; typedef struct LNode {ElemType data; struct LNode *next; }LinkList; void CreatListF(LinkList *&L,ElemType a[],int n) //头插法建表 { LinkList *s;int i; L=(LinkList *)malloc(sizeof(LinkList)); L->next=NULL; for(i=0;i<n;i++) { s=(LinkList *)malloc(sizeof(LinkList)); s->data=a[i]; s->next=L->next; L->next=s; } } void CreateListR(LinkList *&L,ElemType a[],int n) //尾插法建表 { LinkList *s,*r;int i; L=(LinkList *)malloc(sizeof(LinkList)); r=L; for(i=0;i<n;i++) { s=(LinkList *)malloc(sizeof(LinkList)); s->data=a[i]; r->next=s; r=s; } r->next=NULL; } void InitList(LinkList *&L) //初始化线性表 { L=(LinkList *)malloc(sizeof(LinkList)); L->next=NULL; } void DestroyList(LinkList *&L) //销毁线性表 { LinkList *p=L,*q=p->next; while(q!=NULL) { free(p); p=q; q=p->next; } free(p); } int ListEmpty(LinkList *L) //判断线性表是否为空 { return(L->next==NULL); } int ListLength(LinkList *L) //求线性表的长度 { LinkList *p=L;int n=0; while(p->next!=NULL) { n++;p=p->next; } return(n); } void DispList(LinkList *L) //输出线性表 { LinkList *p=L->next; while(p!=NULL) { printf("%c",p->data); p=p->next; } } int GetElem(LinkList *L,int i,ElemType &e) //求线性表中某个数据元素值 { int j=0; LinkList *p=L; while(j<i&&p!=NULL) { j++;p=p->next; } if(p==NULL) return 0; else { e=p->data;return 1; } } int LocateElem(LinkList *L,ElemType e) //按元素值查找 { LinkList *p=L->next; int i=1; while(p!=NULL&&p->data!=e) { p=p->next;i++; } if(p==NULL)return(0); else return(i); } int ListInsert(LinkList *&L,int i,ElemType e) //插入数据元素 { int j=0; LinkList *p=L,*s; while(j<i-1&&p!=NULL) { j++;p=p->next; } if(p==NULL)return 0; else { s=(LinkList *)malloc(sizeof(LinkList)); s->data=e; s->next=p->next; p->next=s; return 1; } } int ListDelete(LinkList *&L,int i,ElemType &e) //删除数据元素 { int j=0; LinkList *p=L,*q; while(j<i-1&&p!=NULL) { j++;p=p->next; } if(p==NULL) return 0; else { q=p->next; if(q==NULL)return 0; e=q->data; p->next=q->next; free(q); return 1; } } int main() { ElemType e,a[5]={'a','b','c','d','e'}; LinkList *h; InitList(h); //初始化顺序表h CreateListR(h,&a[0],5); //依次采用尾插入法插入a,b,c,d,e元素 printf("单链表为:"); DispList(h); printf("\n"); //输出顺序表h printf("该单链表的长度为:"); printf("%d",ListLength(h)); printf("\n"); //输出顺序表h的长度 if(ListEmpty(h)) printf("该单链表为空。\n"); else printf("该单链表不为空。\n"); //判断顺序表h是否为空 GetElem(h,3,e);printf("该单链表的第3个元素为:"); printf("%c",e); printf("\n"); //输出顺序表h的第3个元素 printf("该单链表中a的位置为:"); printf("%d",LocateElem(h,'a')); printf("\n"); //输出元素'a'的位置 ListInsert(h,4,'f'); //在第4个元素位置插入'f'素 printf("在第4 个元素位置上插入'f'后单链表为:"); DispList(h); printf("\n"); //输出顺序表h ListDelete(h,3,e); //删除L的第3个元素 printf("删除第3个元素后单链表为:"); DispList(h); printf("\n"); //输出顺序表h DestroyList(h); //释放顺序表h return 0; }
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值