王道数据结构课后代码题p40 第7——12题 (c语言代码实现)

目录

[7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素 (c语言代码实现)](#7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素 (c语言代码实现))

8.给定两个单链表,编写算法找出两个链表的公共结点(c语言代码)

[9.给定一个带表头结点的单链表,写出算法 : 按递增次序输出单链表中各结点的数据元素并释放结点 (c语言代码实现)](#9.给定一个带表头结点的单链表,写出算法 : 按递增次序输出单链表中各结点的数据元素并释放结点 (c语言代码实现))

10.将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变(c语言代码)

11.C={a1,b1,a2,b2,...,an,bn}为线性表,采用带头结点的单链表存放,设计一个就地算法,将其拆分为两个线性表,使得A={a1..an},B={bn,.,b1}

12.在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素,例如(7,10,10,21,30,42,42,42,51,70)将变为(7,10,21,30,42,51,70)。


7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素的元素 (c语言代码实现)

本题代码为(有注释)

void delete(linklist* L, int min, int max)//删除给定的两个值之间的元素
{
	lnode* p = (*L)->next, * q = *L;
	while (p != NULL)
	{
		if (p->data > min && p->data < max)//判断在是否在两个值的中间
		{
			q->next= p->next;//使q的后继指向p的后继
			free(p);//释放p的内存
			p = q->next;//使p指向q的后继
		}
		else
		{
			q = q->next;//q跟p都想后遍历
			p = p->next;
		}
	}
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct lnode
{
	int data;
	struct lnode* next;
}lnode,*linklist;
int n = 6;
int a[6] = { 3,2,4,9,8,7 };
void buildlinklist(linklist* L)
{
	*L = (lnode*)malloc(sizeof(lnode));
	(*L)->next = NULL;
	int i = 0;
	lnode* s = *L, * r = *L;
	for (i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		s->next = r->next;
		r->next = s;
		r = s;
	}
	r->next = NULL;
}
void delete(linklist* L, int min, int max)//删除给定的两个值之间的元素
{
	lnode* p = (*L)->next, * q = *L;
	while (p != NULL)
	{
		if (p->data > min && p->data < max)//判断在是否在两个值的中间
		{
			q->next= p->next;//使q的后继指向p的后继
			free(p);//释放p的内存
			p = q->next;//使p指向q的后继
		}
		else
		{
			q = q->next;//q跟p都想后遍历
			p = p->next;
		}
	}
}
void print(linklist* L)
{
	lnode* k = (*L)->next;
	while (k != NULL)
	{
		printf("%d ", k->data);
		k = k->next;
	}
}
int main()
{
	linklist L;
	buildlinklist(&L);
	printf("原始单链表为:");
	print(&L);
	delete(&L,2,6);
	printf("\n删除后的单链表为:");
	print(&L);
	return 0;
}

8.给定两个单链表,编写算法找出两个链表的公共结点(c语言代码)

两个链表有公共结点,就是两个链表从某一结点开始,它们的next都指向同一个结点

本题代码如下

int length(linklist* L)//计算链表长度
{
    int j = 0;
    lnode* p = (*L)->next;
    while (p != NULL)
    {
        j++;
        p = p->next;
    }
    return j;
}
linklist* findcommon(linklist* L1, linklist* L2)
{
    int len1 = length(L1);//计算两个链表的长度
    int len2 = length(L2);
    int dist = 0;
    linklist longlist, shortlist;//分别指向长的链表和短的链表
    if (len1 > len2)//L1较长
    {
        longlist = (*L1)->next;
        shortlist = (*L2)->next;
        dist = len1 - len2;//表长之差
    }
    else//L2表长
    {
        longlist = (*L2)->next;
        shortlist = (*L1)->next;
        dist = len2 - len1;
    }
    while (dist--)//表长的先遍历到第dist个结点
        longlist = longlist->next;
    while (longlist != NULL)//同步寻找共同结点
    {
        if (longlist->data== shortlist->data)//找到第一个公共结点
            return longlist->data;
        else//没没找到就继续寻找
        {
            longlist = longlist->next;
            shortlist = shortlist->next;
        }
    }
    return NULL;
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct lnode
{
    int data;
    struct lnode* next;
} lnode, * linklist;
int a[5] = { 1,3,5,6,7};
int b[4] = { 2,9,6,7};
int n1 = 5;
int n2 = 4;
void buildlinklist(linklist* L, int arr[], int n)
{
    *L = (lnode*)malloc(sizeof(lnode));
    (*L)->next = NULL;
    int i = 0;
    lnode* s = *L, * r = *L;
    for (i = 0; i < n; i++)
    {
        s = (lnode*)malloc(sizeof(lnode));
        s->data = arr[i];
        s->next = r->next;
        r->next = s;
        r = s;
    }
    r->next = NULL;
}
int length(linklist* L)//计算链表长度
{
    int j = 0;
    lnode* p = (*L)->next;
    while (p != NULL)
    {
        j++;
        p = p->next;
    }
    return j;
}
linklist* findcommon(linklist* L1, linklist* L2)
{
    int len1 = length(L1);//计算两个链表的长度
    int len2 = length(L2);
    int dist = 0;
    linklist longlist, shortlist;//分别指向长的链表和短的链表
    if (len1 > len2)//L1较长
    {
        longlist = (*L1)->next;
        shortlist = (*L2)->next;
        dist = len1 - len2;//表长之差
    }
    else//L2表长
    {
        longlist = (*L2)->next;
        shortlist = (*L1)->next;
        dist = len2 - len1;
    }
    while (dist--)//表长的先遍历到第dist个结点
        longlist = longlist->next;
    while (longlist != NULL)//同步寻找共同结点
    {
        if (longlist->data== shortlist->data)//找到第一个公共结点
            return longlist->data;
        else//没没找到就继续寻找
        {
            longlist = longlist->next;
            shortlist = shortlist->next;
        }
    }
    return NULL;
}
int main()
{
    linklist L1;
    linklist L2;
    linklist L3 = (lnode*)malloc(sizeof(lnode));
    buildlinklist(&L1, a, n1);
    buildlinklist(&L2, b, n2);
    L3->data= findcommon(&L1, &L2);
    if (L3 != NULL)
    {
        printf("找到公共节点: %d\n", L3->data);
    }
    else
    {
        printf("没有找到公共节点\n");
    }
    return 0;
}

9.给定一个带表头结点的单链表,写出算法 : 按递增次序输出单链表中各结点的数据元素并释放结点 (c语言代码实现)

本题代码如下(有注释)

void delete_min(linklist* head)
{
	while ((*head)->next != NULL)//循环到只剩下头节点
	{
		lnode* pre = *head;//pre为元素最小结点的前驱结点指针
		lnode* p = (*head)->next;//p为工作指针
		lnode* q;//指向被删除的结点
		while (p->next != NULL)//找到最小的结点
		{
			if (p->next->data < pre->next->data)
				pre = p;//记住当前最小值的前驱
			p = p->next;
		}
		printf("%d ", pre->next->data);//输出最小值结点的数据
		q = pre->next;//p指向最小结点
		pre->next = q->next;//pre后继指向q的后继
		free(q);//释放q结点
	}
	free(*head);//释放头节点
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct lnode
{
	int data;
	struct lnode* next;
}lnode,*linklist;
int n = 5;
int a[5] = { 2,1,9,8,7 };
void buildlinklist(linklist* head)//建立单链表
{
	*head = (lnode*)malloc(sizeof(lnode));
	(*head)->next = NULL;
	int i = 0;
	lnode* s = *head, * r = *head;
	for (i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		s->next = r->next;
		r->next = s;
		r = s;
	}
	r->next = NULL;
}
void delete_min(linklist* head)
{
	while ((*head)->next != NULL)//循环到只剩下头节点
	{
		lnode* pre = *head;//pre为元素最小结点的前驱结点指针
		lnode* p = (*head)->next;//p为工作指针
		lnode* q;//指向被删除的结点
		while (p->next != NULL)//找到最小的结点
		{
			if (p->next->data < pre->next->data)
				pre = p;//记住当前最小值的前驱
			p = p->next;
		}
		printf("%d ", pre->next->data);//输出最小值结点的数据
		q = pre->next;//p指向最小结点
		pre->next = q->next;//pre后继指向q的后继
		free(q);//释放q结点
	}
	free(*head);//释放头节点
}
int main()
{
	linklist head;
	buildlinklist(&head);
	delete_min(&head);
	return 0;
}

10.将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变(c语言代码)

设置一个访问变量(初值为0),每访问一个结点序号自动加1,然后根据序号的奇偶性将结点插入到A表或B表中,用while循环重复以上操作直到表尾

本题代码如下

linklist discreat(linklist* L)
{
	lnode* B = (lnode*)malloc(sizeof(lnode));//创建B表的表头
	B->next = NULL;//B表初始化
	int i = 0;
	lnode* p = (*L)->next;//p为工作指针
	lnode* ra = *L,*rb=B;//ra指向A表尾,rb指向B表尾
	while (p != NULL)
	{
		i++;
		if (i % 2 == 0)//处理偶数序列的链表结点
		{
			rb->next = p;
			rb = p;
		}
		else//处理原序号为奇数的结点
		{
			ra->next = p;
			ra = p;
		}
		p = p->next;//p指向下一个待处理的结点
	}
	ra->next = NULL;
	rb->next = NULL;
	return B;
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct lnode
{
	int data;
	struct lnode* next;
}lnode,*linklist;
int n = 6;
int a[6] = { 1,2,3,4,5,6 };
void buildlinklist(linklist* L)
{
	*L = (lnode*)malloc(sizeof(lnode));
	(*L)->next = NULL;
	lnode* s = *L, * r = *L;
	int i = 0;
	for (i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		s->next = r->next;
		r->next = s;
		r = s;
	}
	r->next =NULL;
}
linklist discreat(linklist* L)
{
	lnode* B = (lnode*)malloc(sizeof(lnode));//创建B表的表头
	B->next = NULL;//B表初始化
	int i = 0;
	lnode* p = (*L)->next;//p为工作指针
	lnode* ra = *L,*rb=B;//ra指向A表尾,rb指向B表尾
	while (p != NULL)
	{
		i++;
		if (i % 2 == 0)//处理偶数序列的链表结点
		{
			rb->next = p;
			rb = p;
		}
		else//处理原序号为奇数的结点
		{
			ra->next = p;
			ra = p;
		}
		p = p->next;//p指向下一个待处理的结点
	}
	ra->next = NULL;
	rb->next = NULL;
	return B;
}
void print(linklist* L)//输出单链表
{
	lnode* q = (*L)->next;
	while (q)
	{
		printf("%d ", q->data);
		q = q->next;
	}
}
int main()
{
	linklist L,B;
	buildlinklist(&L);
	printf("原始单链表为:");
	print(&L);
	B=discreat(&L);
	printf("\nA链表为:");
	print(&L);
	printf("\nB链表为:");
	print(&B);
	return 0;
}

11.C={a1,b1,a2,b2,...,an,bn}为线性表,采用带头结点的单链表存放,设计一个就地算法,将其拆分为两个线性表,使得A={a1..an},B={bn,.,b1}

本题A链表应用尾插法,B链表应用头插法

linklist chaifen(linklist* L)//A链表用尾插法,B链表用头插法
{
	lnode* B = (lnode*)malloc(sizeof(lnode));
	B->next = NULL;
	lnode* p = (*L)->next, * ra = *L, * q;//p为工作指针,ra始终指向A的为结点
	while (p != NULL)
	{
		ra->next = p;
		ra = p;//将*p链接到A的表尾
		p = p->next;
		if (p != NULL)
		{
			q = p->next;//用q记录p的后继
			p->next = B->next;//将*p插入到B的前端
			B->next = p;
			p = q;
		}
	}
	ra->next = NULL;//A为结点的next域置空
	return B;
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct lnode
{
	int data;
	struct lnode* next;
}lnode,*linklist;
int n = 6;
int a[6] = { 1,2,3,4,5,6 };
void buildlinklist(linklist* L)
{
	*L = (lnode*)malloc(sizeof(lnode));
	(*L)->next = NULL;
	int i = 0;
	lnode* s = *L, * r = *L;
	for (i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		s->next = r->next;
		r->next = s;
		r = s;
	}
	r->next = NULL;
}
linklist chaifen(linklist* L)//A链表用尾插法,B链表用头插法
{
	lnode* B = (lnode*)malloc(sizeof(lnode));
	B->next = NULL;
	lnode* p = (*L)->next, * ra = *L, * q;//p为工作指针,ra始终指向A的为结点
	while (p != NULL)
	{
		ra->next = p;
		ra = p;//将*p链接到A的表尾
		p = p->next;
		if (p != NULL)
		{
			q = p->next;//用q记录p的后继
			p->next = B->next;//将*p插入到B的前端
			B->next = p;
			p = q;
		}
	}
	ra->next = NULL;//A为结点的next域置空
	return B;
}
void print(linklist* L)//输出单链表
{
	lnode* k = (*L)->next;
	while (k)
	{
		printf("%d ", k->data);
		k = k->next;
	}
}
int main()
{
	linklist L, B;
	buildlinklist(&L);
	printf("原始单链表为:");
	print(&L);
	B = chaifen(&L);
	printf("\nA链表为:");
	print(&L);
	printf("\nB链表为:");
	print(&B);
	return 0;
}

12.在一个递增有序的线性表中,有数值相同的元素存在。

若存储方式为单链表,设计算法去掉数值相同的元素,使表中不再有重复的元素,例如(7,10,10,21,30,42,42,42,51,70)将变为(7,10,21,30,42,51,70)。

由于是有序表,所有相同值域的结点都是相邻的。用p扫描递增单链表L,若*p结点的值域等于其后继结点的值域,则删除后者,否则p移向下一个结点

本题代码如下

void deleterepeat(linklist* L)//删除重复的元素
{
	lnode* p = (*L)->next, * q;//p为扫描工作指针
	while (p->next!= NULL)
	{
		q = p->next;//q指向p的后继
		if (p->data == q->data)//如果p的后继与p相等
		{
			p->next = q->next;//p的后继就指向q的后继,也就是p的后继的后继
			free(q);//释放q结点
		}
		else
		{
			p = p->next;//p继续往后遍历
		}
	}
}

完整测试代码

#include<stdio.h>
#include<stdlib.h>
typedef struct lnode
{
	int data;
	struct lnode* next;
}lnode,*linklist;
int n = 10;
int a[10] = { 7,10,10,21,30,42,42,42,51,70 };
void buildlinklist(linklist* L)
{
	*L = (lnode*)malloc(sizeof(lnode));
	(*L)->next = NULL;
	lnode* s = *L, * r = *L;
	int i = 0;
	for (i = 0; i < n; i++)
	{
		s = (lnode*)malloc(sizeof(lnode));
		s->data = a[i];
		s->next = r->next;
		r->next = s;
		r = s;
	}
	r->next = NULL;
}
void deleterepeat(linklist* L)//删除重复的元素
{
	lnode* p = (*L)->next, * q;//p为扫描工作指针
	while (p->next!= NULL)
	{
		q = p->next;//q指向p的后继
		if (p->data == q->data)//如果p的后继与p相等
		{
			p->next = q->next;//p的后继就指向q的后继,也就是p的后继的后继
			free(q);//释放q结点
		}
		else
		{
			p = p->next;//p继续往后遍历
		}
	}
}
void print(linklist* L)//输出的单链表
{
	lnode* k = (*L)->next;
	while (k != NULL)
	{
		printf("%d ", k->data);
		k = k->next;
	}
}
int main()
{
	linklist L;
	buildlinklist(&L);
	printf("原单链表为:");
	print(&L);
	deleterepeat(&L);
	printf("\n修改后的链表为:");
	print(&L);
	return 0;
}
相关推荐
励志成为嵌入式工程师2 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉2 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer2 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq2 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown3 小时前
【数据结构】选择排序
数据结构·算法·排序算法
hikktn4 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
观音山保我别报错4 小时前
C语言扫雷小游戏
c语言·开发语言·算法
TangKenny5 小时前
计算网络信号
java·算法·华为
景鹤5 小时前
【算法】递归+深搜:814.二叉树剪枝
算法
iiFrankie5 小时前
SCNU习题 总结与复习
算法