链表的合并,结点逆置,顺序表的高效划分(数据结构作业02)

目录

链表的合并

链表的结点逆置

 顺序表的高效划分


链表的合并

        已知两个递增有序的单链表A和B,分别表示两个集合。试设计一个算法,用于求出A与B的交集,并存储在C链表中。例如 : La = {2,4,6,8};Lb = {4,6,8,10};Lc = {4,6,8}。(要求上机实现完整程序代码、核心代码有注释,有运行结果)。 

        算法分析:遍历这两个链表A和B,使用两个指针,创建一个新的空链表C,然后比较当前节点的数据,如果相等,则将该数据添加到链表C中,然后同时移动两个链表的指针。如果不相等,则移动较小值所在链表的指针。这样可以确保只添加两个链表中共有的元素到链表C中。 

#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode  
{
	ElemType data;
	struct LNode *next;		//指向后继结点
} LinkNode;		

//创建单链表,头插法
LinkNode * createlist(int a[],int len) {
	//len是链表的长度
	LinkNode * L;
	LinkNode * s;
	L = (LinkNode *)malloc(sizeof(LinkNode));
	L -> next = NULL;//创建头结点,next指向为空
	for(int i = 0; i < len; i++) {
		s = (LinkNode*)malloc(sizeof(LinkNode));//创建结点s
		s -> data = a[i];
		s -> next = L -> next; //将s插入原首节点前,头结点后
		L -> next = s;
	}
	return L;
}

//用于打印链表
//由于存储链表使用的是头插法,所以打印时我们现将链表存入一个数组
//再将那个数组反向输出就是我们需要的样子
void printlist(LinkNode *L) {
	LinkNode *p = L -> next;//让p指向首结点
	int arr[4];
	int len = 0,i = 0;
	while(p != NULL) {
		arr[i] = p -> data;
		p = p -> next;
		i++,len++;
		//只要没到尾结点就一直存入arr数组
	}
	len = len - 1;//最后多加了一次len所以要减去
	for(int i = len; i >= 0; i--) {
		printf("%d ",arr[i]);
	}
	printf("\n");
}

//求两个链表的交集
LinkNode * intersection(LinkNode *a,LinkNode *b) {
	//传入a,b两个链表
	LinkNode *c;
	c = (LinkNode *)malloc(sizeof(LinkNode));
	LinkNode *r = c;
	//创建链表c的头结点,使用尾插法
	a = a -> next,b = b -> next;
	//让链表a和链表b指向它们的首结点
	LinkNode *p;
	while(a != NULL && b != NULL) {
		if(a -> data == b -> data) {
			//若二值相等,使用尾插法存入c中,并且让这两个指针都往后移动
			p = (LinkNode *)malloc(sizeof(LinkNode));
			p -> data = a -> data;
			r -> next = p;
			r = r -> next;
			
			a = a -> next,b = b -> next;
		}
		else {
			//由于创建列表时使用了尾插法,所以要变得相反
			//若二值不相等则值更大的往后移一格
			if(a -> data > b -> data)
				a = a -> next;
			if(b -> next > a -> next)
				b = b -> next;
		}
	}
	r -> next = NULL;
	//尾插法注意要让尾结点的next域置为空
	return c;
}

int main() {
	//创建链表a
	int a[4];
	a[0] = 2,a[1] = 4,a[2] = 6,a[3] = 8;
	LinkNode *la;
	la = createlist(a,4);
	printf("链表a为:");
	printlist(la);
	
	//创建链表b
	int b[4];
	b[0] = 4,b[1] = 6,b[2] = 8,b[3] = 10;
	LinkNode *lb;
	lb = createlist(b,4);
	printf("链表b为:");
	printlist(lb);
	
	//得到链表la和lb的交集lc
	LinkNode *lc = intersection(la,lb);
	printf("链表a和链表b的交集链表c为:");
	printlist(lc);
}

 

链表的结点逆置

        假设有一个带头结点的单链表L=(2,4,6…,20)。设计一个算法将所有结点逆置,即:L=(20,18,…,2)。(要求要求上机实现完整程序代码、核心代码有注释,有运行结果) 

        算法分析:可以使用尾插法建立第一个链表,再写一个逆置函数,传入这个链表,在函数里面改变当前节点的指针使其指向其前一个节点,以此类推,直到遍历完所有的节点。 

#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode  
{
	ElemType data;
	struct LNode *next;		//指向后继结点
} LinkNode;		

//创建单链表,尾插法
LinkNode * createlist(int a[],int len) {
	LinkNode *L,*r,*s;
	L = (LinkNode*)malloc(sizeof(LinkNode));
	//L为头结点
	r = L;
	for(int i = 0; i < len; i++) {
		s = (LinkNode *)malloc(sizeof(LinkNode));
		s -> data = a[i];
		r -> next = s;
		r = r -> next;
		//将数据存入s中并且让r的next指向它
		//再将r向后移动一格
	}
	r -> next = NULL;
	//记得要让尾结点的next域为空
	return L;
}

//打印单链表
void printlist(LinkNode * l) {
	l = l -> next;
	//让l指向它的首结点
	while(l != NULL) {
		printf("%d ",l -> data);
		l = l -> next;
	}
	printf("\n");
}

//打印逆置后的单链表
void printreverselist(LinkNode *l) {
	//采用这种逆置方法后不用指向首结点,此时l即为首结点
	while(l != NULL) {
		printf("%d ",l -> data);
		l = l -> next;
	}
	printf("\n");
}

//逆置链表函数
LinkNode * reverselist(LinkNode * head) {
	//创建新的头结点p
	LinkNode *p;
	
	LinkNode *l,*r;
	l = head -> next;
	//l表示left,是左边的指针
	//r表示right,是右边的指针
	//让s指向首结点,头结点的next指向空
	head -> next = NULL;
	
	//核心代码
	while(l != NULL) {
		r = l -> next;//保存当前节点的下一个节点
		l -> next = p;//将当前节点的next指向前一个节点
		p = l;//更新p为当前节点
		l = r;//移动到下一个节点
	}
	return p;
}

int main() {
	//创建逆置前的链表
	int a[100];
	int n = 1;
	for(int i = 0; i < 10; i++) {
		a[i] = 2 * n;
		n++;
	}
	LinkNode *l = createlist(a,10);
	printf("逆置前的链表为:");
	printlist(l);
	
	//逆置链表
	l = reverselist(l);
	printf("逆置后的链表为:");
	printreverselist(l);
}

 

 顺序表的高效划分

        对有n个整形元素的顺序表以第一个元素为基准进行高效划分,将所有大于该基准的所有元素放在该基准的右边;将所有小于等于该基准的所有元素放在该基准的左边。例如对于线性表(17,2,3,5,4,20,1,18,19,20,21,6,22)要求要求上机实现完整程序代码、核心代码有注释,有运行结果)

#include <stdio.h>
#include <malloc.h>
#define MaxSize 50
typedef int ElemType; 
typedef struct 
{	int data[MaxSize];		//存放顺序表元素
	int length;					//存放顺序表的长度
} SqList;						//顺序表的类型

//建立顺序表
SqList * createlist(int a[],int len) {
	SqList *l;
	l = (SqList *)malloc(sizeof(SqList));
	int k = 0;
	//k用于记录顺序表的长度
	for(int i = 0; i < len; i++) {
		l -> data[i] = a[i];
		k++;
	}
	l -> length = k;
	return l;
}

void partitionlist(SqList * list) {
	int l = 0,r = list -> length - 1;
	//让l指向头,r指向尾
	
	int base = list -> data[0];
	//将第一个数设置为基准
	
	while(l < r) {
		while(r > l && list -> data[r] > base)
			r--;
		//先从右往左遍历,找到第一个小于等于base的数
		list -> data[l] = list -> data[r];
		//将这个数放入l的位置上
		
		while(l < r && list -> data[l] <= base)
			l++;
		//再从左往右,找到第一个大于base的数
		list -> data[r] = list -> data[l];
		//将这个数放在r的位置上
	}
	list -> data[l] = base;
	//最后把这个数放在位置l处
}

//打印顺序表
void printlist(SqList *l) {
	for(int i = 0; i < l -> length; i++) {
		printf("%d ",l -> data[i]);
	}
	printf("\n");
}

int main() {
	//创建顺序表
	int arr[100];
	arr[0] = 17;arr[1] = 2;arr[2] = 3;arr[3] = 5;arr[4] = 4;
	arr[5] = 20;arr[6] = 1;arr[7] = 18;arr[8] = 19;arr[9] = 20;
	arr[10] = 21;arr[11] = 6;arr[12] = 22;
	SqList *l;
	l = createlist(arr,13);
	printf("初始的顺序表为:");
	printlist(l);
	
	//进行高效划分
	partitionlist(l);
	printf("高效划分后的顺序表为:");
	printlist(l);
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏箱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值