(二)、线性表

目录

 线性表的顺序存储(顺序表)

线性表的链式存储(重点)


        线性表(List)是由n个形同类型的数据元素构成的有限序列。记为:L=(a1,a2,···,ai,···,an),将ai-1称为ai的直接前驱,将ai+1称为ai的直接后继。

        线性表的形式化定义:线性表(List)简记为L,是一个二元组,L=(D,R),D是数据元素的有限集合,R是数据元素之间关系的有限集合。

Linear_List=(D, S )
D={ ai | ai∈elemset,1≤i≤n}
S={ 〈ai,ai+1〉 | 1≤i≤n−1 }

线性表的特征:

1)对非空表,a0是表头,无前驱;

2)an-1是表尾,无后继;

3)其他的每个元素ai有且仅有一个直接前驱ai-1和一个直接后继ai+1。

 线性表的顺序存储(顺序表)

                                     

last代表最后一个元素的下表,最大是N-1。

线性表的顺序存储缺点:

       线性表的顺序存储结构有存储密度高以及能够随机存取等优点,但存在以下不足:

(1) 要求系统提供一片较大的连续存储空间。

(2) 插入、删除等运算耗时,且存在元素在存储区域内成片移动的现象。

线性表常用代码

sqlist.c(相关函数的实现)

#include "sqlist.h"

/*
	建立一个线性表
 */
sqlink list_create()
{
	sqlink L;
	L=(sqlink)malloc(sizeof(sqlist));
	if(L==NULL)
		printf("malloc failed\n");
	memset(L,0,sizeof(sqlist));
	L->last=-1;   //last=-1代表线性表为空
	return L;
}
/*
	删除线性表
 */
int list_free(sqlink L)
{
	if(L==NULL)
		return -1;
	free(L);
	L=NULL;
	return 0;	
}
/*
	清空线性表
 */
int list_clear(sqlink L)
{   
    if(L==NULL)
		return -1;//如果传入的是空表,返回-1
	memset(L,0,sizeof(sqlist));
	L->last=-1;	
	return 0;	//成功之后返回0
}
/*
	检查线性表是否为空,空返回1,非空返回0
 */
int list_empty(sqlink L)
{
	if(L->last==-1)
		return 1;
	else
		return 0;
}
/*
	求线性表的长度
 */
int list_length(sqlink L)
{
	if(L==NULL)
		return -1;
	return(L->last+1);
}
/*
	看value是否在L中,有就返回pos,无就返回-1
 */
int list_locate(sqlink L,data_t value)
{
	int i;
	for(i=0;i<=L->last;i++)
	{
		if(L->data[i]==value)
			return i;
	}
	return -1;
}
/*
	插入数据到线性表
 */
int list_insert(sqlink L,data_t value,int pos)
{   
	int i;
	if(L->last==N-1)
	{
		printf("List Is Full\n");
		return -1;
	}
	if(pos<0||pos>L->last+1)
	{
		printf("pos is invaild\n");
		return -1;
	}
	for(i=L->last;i>=pos;i--)//如果让i=pos,i++的话会导致最后一个元素再往后移动的过程中丢失
	{
		L->data[i+1]=L->data[i];
	}
	L->data[pos]=value;
	L->last++;
	return 0;
}
/*  
	删除掉指定位置的数据
 */
int list_delete(sqlink L,int pos)
{   
	int i;
	if(L->last==-1)
	{	
		printf("it is empty");
		return -1;
	}
	if(pos<0||pos>L->last)
	{
		printf("pos is invaild\n");
		return -1;
	}
	for(i=pos;i<L->last;i++)
	{
		L->data[i]=L->data[i+1];	
	}
	L->last--;
	return 0;
}
/*
	合并两个线性表  
 */
int list_merge(sqlink L1,sqlink L2)
{	
	int i=0;
	int ret;
	for(i=0;i<=L2->last;i++)
	{
		ret=list_locate(L1,L2->data[i]);
		if(ret==-1)//ret=-1代表L1中没有这个元素
		{
			if(list_insert(L1,L2->data[i],L1->last+1)==-1)
				return -1;//L1内存溢出,返回-1
		}
	}
	return 0;
}
/*
	删除线性表中的重复元素
 */
int list_purge(sqlink L)
{   
	int i=1;
	int j;
	if(L->last==0)
		return 0;
	while(i<=L->last)
	{
		j=i-1;
		while(j>=0)
		{
			if(L->data[i]==L->data[j])
			{
				list_delete(L,i);
				break;
			}
			else
				j--;
		}
		if(j<0)
		{
			i++;
		}
	}
	return 0;
}
/*
	遍历线性表,打印所有元素
 */
int list_show(sqlink L)
{
	int i;
	if(L==NULL)
		return -1;
	if(L->last==-1)
		printf("List is empty\n");
	for(i=0;i<=L->last;i++)
	{
		printf("%d\n",L->data[i]);
	}
	return 0;
	
}

sqlist.h(头文件) 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define N 128


typedef int data_t;
struct sqlist_t
{
	data_t data[N];
	int last;
};
typedef struct sqlist_t sqlist;
typedef struct sqlist_t* sqlink;


sqlink list_create();
int list_free(sqlink L);
int list_clear(sqlink L);
int list_empty(sqlink L);
int list_length(sqlink L);
int list_locate(sqlink L,data_t value);
int list_insert(sqlink L,data_t value,int pos);
int list_delete(sqlink L,int pos);
int list_merge(sqlink L1,sqlink L2);
int list_purge(sqlink L);
int list_show(sqlink L);

/*typedef struct {
	data_t data[N];
	int last;  
  }sqlist, *sqlink;*/

test.c(测试代码)

#include "sqlist.h"

void test_insert();
void test_delete();
void test_merge();
void test_purge();


int main()
{
    //test_insert();
	//test_delete();
	//test_merge();
	test_purge();
	return 0;
}
void test_insert()
{
	sqlink L1;

	L1=list_create();

	list_insert(L1,10,0);
	list_insert(L1,20,0);
	list_insert(L1,30,0);
	list_insert(L1,40,0);
	list_insert(L1,50,0);
	list_insert(L1,60,0);
	list_show(L1);
	
}

void test_delete()
{
	sqlink L1;
	
	L1=list_create();
	
	list_insert(L1,10,0);
	list_insert(L1,20,0);
	list_insert(L1,30,0);
	list_insert(L1,40,0);
	list_insert(L1,50,0);
	list_insert(L1,60,0);
	list_delete(L1,3);
	list_show(L1);
}

void test_merge()
{
	sqlink L1;
	sqlink L2;
	L1=list_create();
	L2=list_create();

	list_insert(L1,10,0);
	list_insert(L1,20,0);
	list_insert(L1,30,0);
	list_insert(L1,40,0);
	list_insert(L1,50,0);
	list_insert(L1,60,0);
	list_insert(L2,90,0);
	list_insert(L2,60,0);
	list_insert(L2,100,0);
	list_insert(L2,00,0);
	list_insert(L2,80,0);
	list_insert(L2,70,0);
	list_show(L1);
	list_show(L2);
	list_merge(L1,L2);
	list_show(L1);
}

void test_purge()
{
	sqlink L1;
	
	L1=list_create();
	
	list_insert(L1,10,0);
	list_insert(L1,10,0);
	list_insert(L1,20,0);
	list_insert(L1,10,0);
	list_insert(L1,10,0);
	list_insert(L1,10,0);
	list_show(L1);
	printf("\n\n\n");
	list_purge(L1);
	list_show(L1);
}

线性表的链式存储(重点)

线性表的链式存储结构:将线性表L=(a0,a1..an-1)中各元素分布在存储器中的不同存储块,称为结点,通过地址或指针建立元素之间的联系。

                                        

结点的data区域存放数据元素ai,而next域是一个指针,指向后继ai+1所在的结点。

     malloc申请的内存在堆上,例如(linklist)malloc(sizeof(linklist)),指针初始化后存放在栈上,例如listnode A,linklist p=&A。动态申请内存时常用malloc。

链式表常用代码

linklist.c(常用函数的实现)

#include "linklist.h"


linklist list_create()
{
	linklist H;
	H=(linklist)malloc(sizeof(listnode));
	if(H==NULL)
		printf("malloc failed\n");
	H->data=0;
	H->next=NULL;
	return H;
}

int list_tail_insert(linklist H,data_t value)//head
{  
	linklist p;//1、创建一个新结点承接value
	linklist q;
	if(H==NULL)
	{
		printf("H is NULL\n");
		return -1;
	}
	if((p=(linklist)malloc(sizeof(listnode)))==NULL)
	{
		printf("malloc failed\n");
		return -1;
	}
	p->data=value;
	p->next=NULL;
	q=H;
	while(q->next!=NULL)//2、找到尾部结点
	{
		q=q->next;
	}
	q->next=p;//3、插入结点	
	return 0;
}
/*
	链表的按序号查找,拿到pos位置的指针
 */
linklist list_get(linklist H,int pos)
{
	linklist p=H;
	int i=0;
	if(p==NULL)
	{
		printf("H is NULL\n");
		return NULL; 
	}
	if(pos==-1)//类似于顺序表,将头设置为-1
	{
		return p;
	}
	if(pos<-1)
	{
		printf("pos is invalid\n");
		return NULL;
	}
	while(i<=pos)//加等于号是因为要从头结点(头结点并不一定是首元结点)开始查找
	{
		p=p->next;
		if(p==NULL)//防止pos太大,造成段错误
		{
			printf("pos is invaild\n");
			return NULL;
		}		
		i++;
	}
	return p;
}
/*
	将新结点插入到pos后面
 */
int list_insert(linklist H,data_t value,int pos)
{
	linklist p;
	linklist q;
	p=list_get(H,pos-1);
	if(p==NULL)
	{
		printf("p is NULL\n");
		return -1;
	}
	if((q=(linklist)malloc(sizeof(listnode)))==NULL)
	{
		printf("malloc failed\n");
		return -1;
	}
	q->data=value;
	q->next=NULL;
	
	q->next=p->next;//一定要先把新结点指针改掉,再去改前面节点的指针
	p->next=q;
	return 0;
}
/*
	删除掉pos处的结点
 */
int list_delete(linklist H,int pos)
{
	linklist p;
	if(H==NULL)
	{
		printf("H is NULL\n");
		return -1;
	}
	p=list_get(H,pos-1);//找到要删除结点的前驱
	linklist q=p->next;
	if(p==NULL)
		return -1;
	if(p->next==NULL)//如果找到的前驱就是尾结点,就退出程序
	{
		printf("delete pos is invaild\n");
		return -1;
	}
    p->next=q->next;
	free(q);
	q=NULL;//防止q成为野指针
	return 0;
}
/*
	清除掉整个链表
 */
int list_free(linklist H)
{	
	linklist p;
	if(H==NULL)
	{
		printf("H is NULL\n");
		return -1;
	}
	while(H!=NULL)
	{
		p=H;
		free(p);
		H=H->next;
	}
}
/*
	遍历打印链表数据
 */
int list_show(linklist H)
{
	linklist p=H;
	if(H==NULL)
	{
		printf("H is NULL\n");
		return -1; 
	}
	while(p->next!=NULL)
	{
		printf("%d",p->next->data);//从首元节点开始打印,头结点中没有数据不打印
		p=p->next;
	}
	puts("");
	return 0;
}
/*
	链表反转
 */
int list_reverse(linklist H)
{
	linklist p;
	linklist q;
	if(H==NULL)
	{
		printf("H is NULL\n");
		return -1;
	}
	if(H->next==NULL||H->next->next==NULL)
	{
		printf("dont need to reverse");
		return -1;
	}

	p=H->next->next; //先把链表断开 断成H->0  和1->2->3
	H->next->next=NULL;
	while(p!=NULL)
	{
		q=p;
		q->next=H->next;//把1节点接到H后面 H->1->0
		H->next=q;
		p=p->next;
	}
	return 0;
}
/*
	合并两个有序链表,并按照顺序排列
 */
int list_merge(linklist H1,linklist H2)
{
	linklist p,q,r;
	if(H1==NULL||H2==NULL)
	{
		printf("H1/H2 is NULL\n");
		return -1;
	}
	p=H1->next;
	q=H2->next;
	r=H1;
	H1->next=NULL;
	H2->next=NULL;
	while(p&&q)
	{
		if(p->data<=q->data)
		{
			r->next=p;
			p=p->next;
			r=r->next;
			r->next=NULL;
		}
		else
		{
			r->next=q;
			q=q->next;
			r=r->next;
			r->next=NULL;
		}
	}
	if(p==NULL)
	{
		r->next=q;
	}
	else
	{
		r->next=p;
	}
	return 0;
}

linklist.h(头文件)

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

typedef int data_t;

typedef struct node
{
	data_t data;
	struct node *next;
}listnode, *linklist;

linklist list_create();
int list_tail_insert(linklist H,data_t value);//head
linklist list_get(linklist H,int pos);
int list_insert(linklist H,data_t value,int pos);
int list_delete(linklist H,int pos);
int list_show(linklist H);
int list_free(linklist H);
int list_reverse(linklist H);
int list_merge(linklist H1,linklist H2);

test.c(测试代码)

int main()
{
	//test_get();
	//test_insert();
	test_delete();
	
}

void test_get()
{
	linklist H;
	linklist p;
	int value;
	H=list_create();
	printf("input:");
	while(1)
	{
		scanf("%d",&value);
		if(value==-1)
			break;
		list_tail_insert(H,value);
		printf("input:");
	}
	list_show(H);
	
	p=list_get(H,0);
	if(p!=NULL)//防止p=NULL时,取值造成段错误
		printf("value=%d\n",p->data);
		
}

void test_insert()
{
	linklist H;
	int value;
	H=list_create();
	printf("input:");
	while(1)
	{
		scanf("%d",&value);
		if(value==-1)
			break;
		list_tail_insert(H,value);
		printf("input:");
	}
	list_show(H);
	list_insert(H,100,3);
	list_show(H);
}
void test_delete()
{
	linklist H;
	int value;
	H=list_create();
	printf("input:");
	while(1)
	{
		scanf("%d",&value);
		if(value==-1)
			break;
		list_tail_insert(H,value);
		printf("input:");
	}
	list_show(H);
	list_delete(H,2);
	list_show(H);
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值