C语言线性表总结

顺序存储结构

地址计算方法

结构代码

#define MAXSIZE 20 //分配起始储存空间大小
typedef int ElemType	//数据类型根据实际情况而定
typedef struct
{
	ElemType data[MAXSIZE];	//数组储存数据元素,最大值为MAXSIZE
	int length;	//线性表当前长度
}

地址计算方法

在C语言中,数组是0开始第一个下标的,即第i个元素储存在数组下标为i-1的位置,假设每个数据元素占用B个储存单元,那么对于第i个数据元素Ai的储存位置可以由第一个元素算出,即

LOC(Ai)=LOC(A1)+(i-1)xB

插入与删除

首先要有一个程序,能获得元素。
获得元素操作

#define OK 1
#define error 0
#define ture 1
#define false 0
typedef int Status
//假定顺序线性表已经存在
Status getelem(sqlist L,int i,ElemType *e )
{
	if(L.length==0 || i<1 || i>L.length)	//处理出错情况
	return error;
	*e=L.data[i-1];		//把元素值通过指针赋值给e
	return OK;			//读取成功,返回ok,数据储存在e中
}

插入与删除操作
插入操作思路:

  1. 如果插入位置不合理,提示异常
  2. 如果线性表长度大于等于数组长度,则提示异常或者动态增加容量
  3. 从最后一个元素开始向前遍历到第i个位置,分别将它们向后移动一个位置
  4. 将要插入的元素填进i处
  5. 表长加1
Status ListInsert(sqlist *L,int i,ElemType e)
{
	int k;
	if(L->length==MAXSIZE) //线性表已满
	return error;
	if(i<1 || i > L.length) //不在表的范围内
	return error;
	if(i<=L->length) //插入元素不在表尾
	{
		for(k=L->length;k>=i-1;k--)		//从后往前遍历
		L.data[k+1]=L.data[k];
	}
	L.data[i]=e;		//插入元素e
	L->length++;			//表长加1
	return OK;
}

删除操作思路

  1. 如果删除位置不合理,则抛出异常
  2. 取出删除元素
  3. 从删除元素的位置开始向后遍历,使它们向前移动一位
  4. 表长减1
Sratus ListDelete(sqlist *L,int i,ElemType *e)
{
	int k;
	if(i>MAXSIZE || i<1 || i> L->length || L->length==0)	//处理异常
	return error;
	*e=L->data[i-1];		//取出要删除的元素
	if(i<L->length)		//不在表尾
	{
		for(k=i;k<L->length;k++)
		L.data[k-1]=L.data[k];		//向前移动
	}
	L->length--;			//表长减1
	return OK;
}

优缺点

优点:无需为表示表中元素之间的逻辑关系而增加额外的存储空间。可以快速地存取表中任一位置的元素
缺点:插入和删除操作需要移动大量的元素,当线性表长度变化较大时,难以确定存储空间的容量

链式存储结构

单链表

结构代码

typedef struct Node
{
	ElemType data;		//数据
	struct node * next;	//结构体指针
}Node;
typedef struct Node* LinkList; //用LinkList代替struct Node*

头指针与头节点

链表的第一个结点的存储位置叫做头指针(头指针无论如何也不为空)
。头节点是单链表的第一个结点前附加的一个结点。

读取操作

思路:

  1. 创建一个结点p指向链表的第一个结点,初始化j=1
  2. 当j<i时,遍历链表,让p不断向后移动,指向下一个结点,j累加1
  3. 若超出了链表范围,则说明第i个元素不存在,处理错误
  4. 否则查找成功,返回此时p节点的数据
Status getelem(LinkList L,int i,ElemType*e)
{
	LinkList p;
	p=L->next;		//让p指向链表的第一个结点
	int j=1;
	if(j<i && p)
	{
			p=p->next;		//遍历
			++j;
	}
	if(!p || j>i) //第i个元素不存在
		return error;
	*e=p->data;	//读取数据
	return OK;
}

结点p的值就是结点p的地址

插入操作

思路:

  1. 声明一结点p指向链表的第一个结点,初始化j从1开始
  2. 当j<i时,遍历链表,让p的指针向后移动,j累加一
  3. 若到了链表末尾p为空,则说明第i个元素不存在
  4. 否则查找成功,在系统中生成一个空结点s
  5. 将元素e赋值给空结点 即s.data=e
  6. 然后将结点s插入 ,s.next=p.next; p.next=s;
  7. 返回成功
Status ListInsert(LinkList * L,int i,ElemType e) 	//实参应该为&L,二级指针
{
	Linklist p,s;
	p=*L;
	int j=1;
	if(p && j<i)			//遍历
	{
			p=p->next;	//修改指针本身
			++j;
	}
	if(!p || j>i)
		return error;
	s=(LinkList)malloc(sizeof(Node));	//创建一个空结点s
	s->data=e;
	s->next=p->next;		
	p->next=s;		
	return OK;
}

删除操作

思路:
8. 声明一结点p指向链表的第一个结点,初始化j从1开始
9. 当j<i时,遍历链表,让p的指针向后移动,j累加一
10. 若到了链表末尾p为空,则说明第i个元素不存在
11. 否则查找成功,将要删除的结点p.next赋值给q,q=p.next
12. 单链表删除标准语句 p.next=q.next;
13. 将q结点的数据赋值给e,返回
14. 释放q结点
15. 返回成功

Status ListDelete(sqlist *L,int i,ElemType *e)
{
	int j=1;
	LinkList q;
	LinkList p;
	p=*L;
	if(p && j<i)
	{
			p=p->next;
			++j;
	}
	if(!p || j>i)
		return error;
	q=p->next;
	p->next=q->next;
	*e=q->data;
	free(q);		//释放结点q
	return OK;
}

单链表的整表创建

思路一(表头插队法):

  1. 声明一个结点p和计数器变量i
  2. 初始化空链表L
  3. 让L的头结点指向NULL,即建立一个带头结点的单链表
  4. 循环:生成一新节点赋值给p,随机生成一数字赋值给p的数据域p.data,将p插入到头结点与前一新结点之间
void CreatListhead(LinkList *L,int n)
{
	LinkList p;
	int i;
	srand(time(0));
	*L=(LinkList)malloc(sizeof(Node));	
	(*L)->next=NULL;		//建立一个带头结点的单链表
	for(i=0;i<n;i++)
	{
		p=(LinkList)malloc(sizeof(Node));
		p->data=rand()%100+1;
		p->next=(*L).next;	//插入到表头
		(*L).next=p; 
	}
}

尾插法

void CreatListhead(LinkList *L , int n)
{
	int i;
	LinkList p,q;
	srand(time(0));
	*L=(LinkList)malaoc(sizeof(Node));
	q=*L;			//q为指向尾部的结点
	for(i=0;i<n;i++)
	{
		p=(LinkList)malloc(sizeof(Node));//新结点
		p->data=rand()%100+1;	//随机数赋值
		q->next=p;		//尾部结点指针指向新插入的结点
		q=p;		//将当前的结点定义为尾部结点
	}
	q.next=NULL;	//尾部结点指针为空,当前链表结束
}

单链表的整表删除

思路:

  1. 声明一结点p和q
  2. 将第一个结点赋值给p
  3. 循环:将下一结点赋值给q,释放p;将q赋值给p
Status ClearList(Linklist *L)
{
	LinkList p,q;
	p=(*L)->next;		//p指向第一个结点
	while(p)		//没到表尾
	{
		q=p->next;
		free(p);
		p=q;
	}
	(*L)->next=NULL;		//设置头结点指针域为空
	return OK;
}

后面的不想写了

静态链表

循环链表

双向链表

优缺点

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页