第二章.线性表基本算法

一.线性表的结构体定义

1. 顺序表的结构体定义

#define maxSize 100
typedef struct
{
	int data[maxSize]; //存放顺序表元素的数组
	int length; //存放顺序表的长度
}Sqlist; //顺序表类型的定义

2. 单链表结点定义

typedef struct LNode
{
	int data; //data中存放结点数据域
	struct LNode *next; //指向后继节点的指针
}LNode; //定义单链表结点类型

3. 双链表结点定义

typedef struct DLNode
{
	int data; //data中存放结点的数据域
	struct DLNode *prior; //指向前驱结点的指针
	struct DLNode *next; //指向后继结点的指针
}DLNode; //定义双链表结点类型

二.顺序表的操作

1.已知一个顺序表L,其中的元素递增有序排列,设计一个算法,插入一个 元素x(x为int型)后保持该顺序表仍然递增有序排列(假设插入操作总能成功)
Note1:找出可以让顺序表保持有序的插入位置
Note2:将Note1中找出的位置上以及其后的元素往后移动一个位置,然后将x放置腾出的位置上

int findElem(Sqlist L,int x) //本函数返回第一个比x大的元素的位置
{
	int i;
	for(i=0;i<L.length;++i)
	{
		if(x < L.data[i]) 
		{
			return i; //循环找到第一个比x大的元素的位置
		}
	}
	return i; //如果找不到比x大的元素,此时应该将x插入表尾位置,又因为for循环执行结束的条件是i=L.length,也就是顺序表中最后一个元素的后一个位置,即要插入新元素的位置
}
void insertElem(Sqlist &L,int x) //因为L本身要发生变化,所以要用引用型
{
	int p,i; //p为要插入元素的位置,i循环变量
	p=findElem(L,x);
	for(i=L.length-1;i>=p;--i) //将p位置及以后的元素都往后移动一个位置
	{
		L.data[i+1]=L.data[i];
	}
	L.data[p]=x; //将x放在插入位置p上
	L.length++; //顺序表多了一个元素,表长增加1
}

2.删除顺序表L中下标为p(0≤p≤length-1)的元素,成功返回1,否则返回0并将被删除元素的值赋给e
Note1:只需将p后面的元素都往前移动一个位置覆盖前面的元素即可,最后表长-1

int deleteElem(Sqlist &L,int p,int e)
{
	int i;
	if(p<0||p>L.length-1) //如果p位置非法,则删除失败返回0
		return 0;
	e=L.data[p]; //将被删除元素的值赋给e
	for(i=p;i<L.length-1;++i)
	{
		L.data[i]=L.data[i+1]; //将p后面的元素往前移动一个位置覆盖前面的元素
	}
	L.length--; //表长-1
	return 1; //删除成功返回1
}

三.单链表的操作

1.A和B是两个单链表(带表头结点),其中元素递增有序。设计一个算法,将A和B归并成一个按元素值非递减有序的链表C,C由A和B中的结点组成
Note1:使用尾插法使得新得到的链表C依然递增有序
Note2:链表A与链表B递增有序,从头开始扫描进行比较选取较小的插入链表C
Note3:链表A(链表B)已经插完,只需将剩余链表A(链表B)链接到C即可

void merge(LNode *A,LNode *B,LNode *&C)
{
	LNode *p = A->next; //p跟踪A的最小值点
	LNode *q = B->next; //q跟踪B的最小值点
	LNode *r; //r始终指向C的终端结点
	C=A; //用A的头结点来做C的头结点
	C->next = NULL;
	free(B); //B的头结点已无用,删去
	r=C; //r指向C,因为此时头结点也是终端结点
	while(p!=NULL && q!=NULL)
	{
		if(p->data <= q->data) //p结点的值小于q结点的值 插入p
		{
			r->next = p;
			p = p->next;
			r = r->next;
		}
		else //q结点的值小于p结点的值 插入q
		{
			r->next = q;
			q = q->next;
			r = r->next;
		}
	} 
	r->next = NULL;
	if(p != NULL)
	{
		r->next = p;
	}
	if(q != NULL)
	{
		r->next = q;
	}
}

2.尾插法

void createlistRear(LNode *&C,int a[],int n)
{
	LNode *s,*r; //s用来指向新申请的结点,r始终指向C的终端结点
	int i;
	C = (LNode *)malloc(sizeof(LNode)); //申请C的头结点空间
	C->next = NULL;
	r=C; //r始终指向终端结点,此时头结点就是终端结点
	for(i=0;i<n;++i)
	{
		s = (LNode *)malloc(sizeof(LNode));
		s->data = A[i];
		r-next = s;
		r = r->next;
	}
	r->next = NULL;
}

3.头插法

void createlistHead(LNode *&C,int a[],int n)
{
	LNode *s;
	int i;
	C = (LNode *)malloc(sizeof(LNode));
	C->next = NULL;
	for(i=0;i<n;++i)
	{
		s = (LNode *)malloc(sizeof(LNode));
		s->data = a[i];
		s->next = C->next;
		C->next = s;
	}
}

4.归并成递减的单链表

void merge(LNode *A,LNode *B,LNode *&C)
{
	LNode *p = A->next;
	LNode *q = B->next;
	LNode *s; //用s来接收新的结点
	C = A;
	C->next = NULL;
	free(B);
	while(p!=NULL && q!=NULL)
	{
		if(p->data < q->data)
		{
			s = p;
			p = p->next;
			s->next = C->next;
			C->next = s;
		}
		else
		{
			s = q;
			q = q->next;
			s->next = C->next;
			C->next = s;
		}
	}
	//必须将剩余元素逐个插入C的头部才能得到最终的递减序列
	while(p!=NULL)
	{
		s = p;
		p = p->next;
		s->next = C->next;
		C->next = s;
	}
	while(q!=NULL)
	{
		s = q;
		q = q->next;
		s->next = C->next;
		C->next = s;
	}
}

5.查找链表C(带头结点)中是否存在一个值为x的结点,若存在则删除该结点并返回1,否则返回0
Note1:定义一个指针变量p遍历单链表每遇到一个新结点就检测其值是否为x
Note2:定义一个指针变量q来接收被删除的结点

int findAndDelete(LNode *C,int x)
{
	LNode *p,*q;
	p = C;
	//查找开始
	while(p->next != NULL)
	{
		if(p->next->data == x)
			break;
		p = p->next;
	}
	//查找结束
	if(p->next == NULL) //当p来到最后一个结点,也就是while循环结束条件(p->next==NULL)
		return 0;
	else
	{
		//删除开始
		q = p->next;
		p->next = p->next->next;
		free(q);
		//删除结束
		return 1;
	}
}

四.双链表的操作

1.采用尾插法建立双链表

void createDlistRear(DLNode *&L,int a[],int n)
{
	DLNode *s,*r; //s接收新结点,r始终指向终端结点
	int i;
	L = (DLNode *)malloc(sizeof(DLNode));
	L->prior = NULL;
	L->next = NULL;
	r=L;
	for(i=0;i<n;++i)
	{
		s = (DLNode *)malloc(sizeof(DLNode));
		s->data = a[i];
		//尾插法
		r->next = s;
		s->prior = r;
		r = r->next;
	}
	r->next = NULL;
}

2.查找结点的算法,找到返回结点指针,否则返回NULL

DLNode* findNode(DLNode *C,int x)
{
	DLNode *p = C->next;
	while(p != NULL)
	{
		if(p->data == x)
			break;
		p=p->next; 
	}
	return p; //如果找到,p中内容是结点地址(循环因break结束)如果没找到,则p中内容是NULL(循环因p等于NULL而结束)
}

3.插入结点算法 p之后插入s

s->next = p->next;
s->prior = p;
p->next = s;
s-next-prior = s;

4.删除结点算法 删除p结点的后继节点

q = p->next;
p->next = q-next;
q->next->prior = p;
free(q);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值