第二章代码题(一)

文章详细介绍了如何在顺序表和链表上进行逆置操作,包括原地修改顺序表的逆置方法和链表的头插法逆置。同时,文章还涵盖了在顺序表中查找最小值元素、删除指定值的元素以及寻找特定值的前驱和后继元素的方法。代码示例和验证过程展示了这些操作的实现。
摘要由CSDN通过智能技术生成

前篇:

第一章代码题

2.(1)本题主要考察逆置,并且逆线性表仍占用原线性表的空间,也就是不能创建新的数据结构。即原地修改。

顺序表逆置:

仔细想一下,逆置就是把第一变成最后一个,第二个变成倒数第二个.......这样的话,我们直接交换对应位置的元素即可。那么要进行交换肯定要先获取到元素。并且一个索引从顺序表前面开始进行遍历,另一个从后面开始进行遍历。

答案:
//顺序表可能达到的最大长度
#define MAXSIZE 20

//将int类型重名为ElemType
typedef int ElemType;

//顺序表结构体定义
typedef struct {
	// ElemType类型的容量为MAXSIZE的名为elem的顺序表
	ElemType elem[MAXSIZE];
	//顺序表的长度
	int length; 
}Seqlist;

void reserve(Seqlist* s) {
	int t = 0;
	int n = s->length;
	for (int i = 0, j = n - 1; i < j; i++, j--)
	{
		t = s->elem[j];
		s->elem[j] = s->elem[i];
		s->elem[i] = t;
	}
	
}
验证:
#include <stdio.h>
//顺序表可能达到的最大长度
#define MAXSIZE 20

//将int类型重名为ElemType
typedef int ElemType;

//顺序表结构体定义
typedef struct {
	// ElemType类型的容量为MAXSIZE的名为elem的顺序表
	ElemType elem[MAXSIZE];
	//顺序表的长度
	int length; 
}Seqlist;

void initSeqlist(Seqlist *s) {
	//构建一个空表
	s->length = 0;
}
//任意位置进行插入
void Insert_Seqlist(Seqlist* s,int pos, ElemType x) {

	if (s->length==MAXSIZE)
	{
		printf("表满");
	}
	if (pos<0||pos>s->length)
	{
		printf("位置错");
	}
	//从尾部元素开始,直到要插入的位置结束,元素依次后移
	for (int  i = s->length-1; i >=pos; i--)
	{
		s->elem[i + 1] = s->elem[i];
	}
	s->elem[pos] = x;
	s->length++;
}

void reserve(Seqlist* s) {
	int t = 0;
	int n = s->length;
	for (int i = 0, j = n - 1; i < j; i++, j--)
	{
		t = s->elem[j];
		s->elem[j] = s->elem[i];
		s->elem[i] = t;
	}
	printf("\n逆置顺序表\n[");
	for (int i = 0; i < n; i++)
	{
		if (i != n - 1)
		{
			printf("%d,", s->elem[i]);
		}
		else {
			printf("%d", s->elem[i]);
		}
	}
	printf("]");
}

int main() {
	Seqlist s;
	initSeqlist(&s);
	for (int  i = 0; i < 10; i++)
	{
		Insert_Seqlist(&s,(&s)->length,i);
	}
	printf("初始顺序表\n[");
	for (int  i = 0; i < (&s)->length; i++)
	{
		if (i!= (&s)->length -1)
		{
			printf("%d,", (&s)->elem[i]);
		}
		else {
			printf("%d", (&s)->elem[i]);
		}
	}
	printf("]");
	reserve(&s);
}

执行结果:

 链表逆置:其实链表的头插法就是逆置的操作。那么对于链表来说用头插法就行。这里写的链表时带有头结点的。那么我们先将它的头结点和链表断开,然后遍历链表,使用头插法重新插入即可。

答案:
void reverse(LinkList L) {
//创建两个结点,都用来遍历整个链表,q永远指向p的下一个结点,方便p进行移动。
	LNode* p, * q;
//p指向第一个数据结点
	p = L->next;
//头结点与数据结点断开
	L->next = NULL;
	while (p)
	{
        //先让q移到p的下一个结点
		q = p->next;
        //头插法
		p->next = L->next;
		L->next= p;
		p = q;
	}
	
}
验证:
void reverse(LinkList L) {
	LNode* p, * q,*l;

	p = L->next;
	L->next = NULL;
	while (p)
	{
		q = p->next;
		p->next = L->next;
		L->next= p;
		p = q;
	}
	l = L->next;
	printf("链表逆置\n");
	while (l)
	{
		printf("%d-->", l->data);
		l = l->next;
	}	
}


void  createLinklist(LinkList list1) {
	//定义两个指针,first用来定位表1头结点,node用来创建新结点
	LNode* node,*first;
	first = list1;
	for (int i = 1; i <10; i++)
	{
		node = (LinkList)malloc(sizeof(LNode));
		node->next = NULL;
		if (i % 2 == 1) {
			node->data = i;
			list1->next = node;
			list1 = node;
		}
	}

	reverse(first);
}

int main() {
	//创建链表的头结点
	LinkList list1 = (LinkList)malloc(sizeof(LNode));
	list1->next = NULL;
	createLinklist(list1);
}

执行结果: 

(2)找出最小值元素,定义一个变量初始化为顺序表的首元素。当顺序表中还有比该变量更小的元素时,将其赋给变量。

代码:

void search_min(Seqlist *s) {
	int min = s->elem[0];
	for (int  i = 1; i < s->length; i++)
	{
		if (min > s->elem[i]) {
			min = s->elem[i];
		}
	}
	printf("\n最小的数据元素是%d", min);
}
验证:
//顺序表查找最小的数据元素
void search_min(Seqlist *s) {
	int min = s->elem[0];
	for (int  i = 1; i < s->length; i++)
	{
		if (min > s->elem[i]) {
			min = s->elem[i];
		}
	}
	printf("\n最小的数据元素是%d", min);
}

int main() {
	Seqlist s;
	initSeqlist(&s);
	for (int  i = 0; i < 10; i++)
	{
		Insert_Seqlist(&s,(&s)->length,i);
	}
	printf("初始顺序表\n[");
	for (int  i = 0; i < (&s)->length; i++)
	{
		if (i!= (&s)->length -1)
		{
			printf("%d,", (&s)->elem[i]);
		}
		else {
			printf("%d", (&s)->elem[i]);
		}
	}
	printf("]");
	search_min(&s);
}

执行结果:

 (3)删除所有值为k的元素,使用两个索引,一个v用来确定等于K的位置,另一个i进行遍历,当i对应的元素不等于k时,就将v对应的元素变为该元素。

代码:

//顺序表删除所有值为k的元素
void Del_k(Seqlist* s, ElemType k) {
	int v = 0;
	for (int  i = 0; i < s->length; i++)
	{
		if (s->elem[i] != k) {
			s->elem[v] = s->elem[i];
			v++;
		}
	}
	s->length = v;
	
}
验证:
//顺序表删除所有值为k的元素
void Del_k(Seqlist* s, ElemType k) {
	int v = 0;
	for (int  i = 0; i < s->length; i++)
	{
		if (s->elem[i] != k) {
			s->elem[v] = s->elem[i];
			v++;
		}
	}
	s->length = v;
	printf("\n删除对应元素后的顺序表\n[");
	for (int i = 0; i < s->length; i++)
	{
		if (i != s->length - 1)
		{
			printf("%d,", s->elem[i]);
		}
		else {
			printf("%d", s->elem[i]);
		}
	}
	printf("]");
}

int main() {
	Seqlist s;
	initSeqlist(&s);
	srand(time(NULL));
	for (int  i = 0; i < 10; i++)
	{
		int j = rand() % 11;
		Insert_Seqlist(&s,(&s)->length,j);
	}
	printf("初始顺序表\n[");
	for (int  i = 0; i < (&s)->length; i++)
	{
		if (i!= (&s)->length -1)
		{
			printf("%d,", (&s)->elem[i]);
		}
		else {
			printf("%d", (&s)->elem[i]);
		}
	}
	printf("]");
	Del_k(&s, 2);
}

执行结果:

注意,因为使用了rand函数,所以答案会有所不同。 

(4)找第一个值为x的前驱和后继,这里要注意,如果顺序表的首元素就为x,那么它应该是没有前驱的,相应地,尾部没有后继。对于链表来说,如果是带有头结点的链表,那么尾部结点是没有后继的。

顺序表:

答案:
void searchpos(Seqlist* s, ElemType x) {
	int pre = -1;
	int next = -1;
	if (s->elem[0]==x)
	{
		next = 1;
		printf("\n无前驱,后继是%d", pre, next);
		return;
	}
	if (s->elem[s->length-1]==x)
	{
		pre = s->length - 2;
		printf("\n前驱是%d,无后继", pre, next);
		return;
	}
	for (int i = 0; i < s->length-1; i++)
	{
		if (s->elem[i] == x) {
			pre = i - 1;
			next = i + 1;
			printf("\n前驱是%d,后继是%d", pre, next);
			return;
		}
	}
	printf("数组中无该元素");
	
}
验证:
//查找顺序表的前驱和后继
void searchpos(Seqlist* s, ElemType x) {
	int pre = -1;
	int next = -1;
	if (s->elem[0]==x)
	{
		next = 1;
		printf("\n无前驱,后继是%d", pre, next);
		return;
	}
	if (s->elem[s->length-1]==x)
	{
		pre = s->length - 2;
		printf("\n前驱是%d,无后继", pre, next);
		return;
	}
	for (int i = 0; i < s->length-1; i++)
	{
		if (s->elem[i] == x) {
			pre = i - 1;
			next = i + 1;
			printf("\n前驱是%d,后继是%d", pre, next);
			return;
		}
	}
	printf("数组中无该元素");
	
}
int main() {
	Seqlist s;
	initSeqlist(&s);
	srand(time(NULL));
	for (int  i = 0; i < 10; i++)
	{
		int j = rand() % 11;
		Insert_Seqlist(&s,(&s)->length,j);
	}
	printf("初始顺序表\n[");
	for (int  i = 0; i < (&s)->length; i++)
	{
		if (i!= (&s)->length -1)
		{
			printf("%d,", (&s)->elem[i]);
		}
		else {
			printf("%d", (&s)->elem[i]);
		}
	}
	printf("]");
	searchpos(&s, 2);
}
执行结果:

 链表:这个题我感觉说的有点问题,应该是想拿到链表的前驱和后继的结点的值吧

答案:
//寻找前驱和后继
void searchpos(LinkList L, Elemtype x) {
	LNode* q, * p, * n;
	q = L->next;
    //头结点
	if (q->data==x)
	{
		p = L;
		n = q->next;
	}
	else
	{
		while (q)
		{
            //尾结点
			if (q->next->next == NULL && q->next->data == x) {
				p = q;
				n = NULL;
			}
			else if (q->next->data==x)
			{
				p = q;
				n = q->next->next;
				printf("\n前驱的值为%d,后继的值为%d", p->data, n->data);
				return;
			}
			
		}
	}
  }
验证:
//寻找前驱和后继
void searchpos(LinkList L, Elemtype x) {
	LNode* q, * p, * n;
	q = L->next;
	if (q->data==x)
	{
		p = L;
		n = q->next;
	}
	else
	{
		while (q)
		{
			if (q->next->next == NULL && q->next->data == x) {
				p = q;
				n = NULL;
			}
			else if (q->next->data==x)
			{
				p = q;
				n = q->next->next;
				printf("\n前驱的值为%d,后继的值为%d", p->data, n->data);
				return;
			}
			
		}
	}
  }


void  createLinklist(LinkList list1) {
	//first用来定位表1头结点,,node用来创建新结点
	LNode* node,*first;

	first = list1;
	for (int i = 1; i <10; i++)
	{
		node = (LinkList)malloc(sizeof(LNode));
		node->next = NULL;
		if (i % 2 == 1) {
			node->data = i;
			list1->next = node;
			list1 = node;

		}
	}
	
	//让链表首尾相连
	list1->next = first;
	list2->next = second;

	//从第一个数据节点开始遍历链表
	LinkList cur1 = first->next;
	printf("\n合并前链表1\n");
	while (first != cur1)
	{
		printf("%d--->", cur1->data);
		cur1 = cur1->next;
	}
	 
	//找链表的前驱和后继
	searchpos(first, 3);

}



int main() {
	//创建链表的头结点
	LinkList list1 = (LinkList)malloc(sizeof(LNode));
	list1->next = NULL;
	createLinklist(list1);
}
执行结果:

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值