前篇:
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);
}