数据结构第二节(基本数据结构)

基本数据结构

在本节中,将会介绍关于数据结构的基本类型,如线性表,堆栈和队列

线性表

在数据结构中,线性表是最常见也是使用最频繁的基本数据结构,它可以通过数组实现或者链表实现,下面给出两种不同的实现代码。

//implemented by array
#include<stdio.h>
#include<stdbool.h>
#define MAXSIZE 5
#define ElementType int
typedef struct LNode* List;
struct LNode
{
	ElementType Data[MAXSIZE];
	int last;
};
//make a empty arraylist
List makeEmpty() {
	List ptrl;
	ptrl = (List)malloc(sizeof(struct LNode));
	ptrl->last = 0;
	return ptrl;
}
//find element by value
int findInValue(ElementType value,List ptrl) {
	int i = 0;
	while (i <= ptrl->last) {
		if (value == ptrl->Data[i++]) {
			return i-1;
		}
	}
	return -1;
}
//find element by index
ElementType findInIndex(int index ,List ptrl) {
	if (index > ptrl->last) {
		return -1;
	}
	else {
		return ptrl->Data[index];
	}
}
//check the arraylist is full
bool isFull(List ptrl) {
	if (ptrl->last==MAXSIZE) {
		return true;
	}
	else {
		return false;
	}
}
//check the arraylist is empty
bool isEmptry(List ptrl) {
	if (ptrl->last == 0) {
		return true;
	}
	else {
		return false;
	}
}
//insert by index
void insert(ElementType value, int index, List ptrl) {
	//if list is full,wring!
	if (isFull(ptrl)) {
		printf("warning: now this arraylist is full,can't insert anything.");
		return;
	}
	else if (index<0||index>ptrl->last) {
		printf("warning: the insert position is invalid.");
		return;
	}
	else {
		//if index less than last,need move all the elements between index and last back one place
		for (int i = ptrl->last; i > index; i--) {
			ptrl->Data[i] = ptrl->Data[i - 1];
		}
		ptrl->Data[index] = value;
		ptrl->last++;
	}
}
//delete element by index 
void delete(int index, List ptrl) {
	if (isEmptry(ptrl)) {
		printf("warning: this position isn't exists.");
		return;
	}
	else if(index<0||index>=MAXSIZE){
		printf("warning: ArrayIndex invalid.");
		return;
	}
	else {
		for (int i = index; i < ptrl->last; i++) {
			ptrl->Data[i] = ptrl->Data[i + 1];
		}
		ptrl->last--;
	}
}
//printlist
void printList(List ptrl) {
	for (int i = 0; i < ptrl->last; i++) {
		printf("%d ", ptrl->Data[i]);
	}
	printf("\n");
}
//test code
int main(void) {
	//make empty list
	List L = makeEmpty();
	//
	for (int i = 1; i < 6; i++) {
		insert(i, 0, L);
		printList(L);
	}
	printf("index of %d is %d\n", 3, findInIndex(3,L));
	printf("the %d in %d\n", 1, findInValue(1,L));
	for (int i = 1; i < 6; i++) {
		delete(0, L);
		printList(L);
	}
}
//implemented by linklist
#include<stdio.h>
#include<stdbool.h>
#include "malloc.h"
typedef struct LNode* List;
#define ElementType int
struct LNode
{
	ElementType Data;
	List Next;
};
//get link list length,the empty table has a header, the default length is 0
int length(List ptrl) {
	List temp = ptrl;
	int len = 0;
	while (temp->Next) {
		temp = temp->Next;
		len++;
	}
	return len;
}
//make an empty linked list,generate an empty header(length is 1)
List makeEmpty() {
	List ptrl;
	ptrl = (List)malloc(sizeof(struct LNode));
	ptrl->Next = NULL;
	return ptrl;
}
//check the linklist is empty
bool isEmpty(List ptrl) {
	if(length(ptrl) == 0) {
		return true;
	}
	else {
		return false;
	}
}
//find element by index,the index of the header is 0,(index>=0)
List findInIndex(int index, List ptrl) {
	int i = 0;
	List temp = ptrl;
	while (temp!=NULL&&i<index) {
		temp = temp->Next;
		i++;
	}
	if (i == index) {
		return temp;
	}
	else {
		return NULL;
	}
}
//find element by value
List findInValue(ElementType value, List ptrl) {
	List temp = ptrl;
	while (temp)
	{
		if (temp->Data == value) {
			break;
		}
		temp = temp->Next;
	}
	return temp;
}
//Insert element at specified position(1-the last)
List insert(ElementType value,int index,List ptrl) {
	List temp = findInIndex(index-1,ptrl);
	if (temp==NULL) {
		printf("wanring: the index is invalid.");
		return NULL;
	}
	else {
		List newLNode = (List)malloc(sizeof(struct LNode));
		newLNode->Data = value;
		if (temp->Next==NULL) {
			temp->Next = newLNode;
			newLNode->Next = NULL;
		}
		else {
			newLNode->Next = temp->Next;
			temp->Next = newLNode;
		}
		return ptrl;
	}
}
//print list
void printList(List ptrl) {
	if (isEmpty(ptrl)) {
		return;
	}
	List temp = ptrl->Next;
	
	while (temp) {
		printf("%d ", temp->Data);
		temp = temp->Next;
	}
	printf("\n");
}
//Delete the node at the specified position(0<index<last)
List delete(int index,List ptrl) {
	if (isEmpty(ptrl)) {
		printf("the linked list has been empty.");
		return ptrl;
	}
	List temp = findInIndex(index - 1,ptrl);
	List tempNext= temp->Next;
	if (temp->Next->Next != NULL) {
		temp->Next = tempNext->Next;
	}
	else {
		temp->Next = NULL;
	}
	free(tempNext);
	return ptrl;
}
int main(void) {
	List L = makeEmpty();
	L = insert(3, 1, L);
	printList(L);
	L = insert(5, 1, L);
	printList(L);
	L = insert(1, 1, L);
	printList(L);
	L = delete(2, L);
	printList(L);
	printf("%d", length(L));
}

在通过链表实现线性表时,常见的做法是建立一个空表头不存储任何数据,当表头的下一个指向为空时,线性表为空,这样做虽然会在内存上有一点的浪费,但操作起来相对更方便。

堆栈

对于一个堆栈,他特有的性质是先进后出,后进先出,就像把盘子叠在一起,最后放在上面的盘子会被更早用到。同样可以用数组实现或是链实现。

#include<stdio.h>
#include<stdbool.h>
#include "malloc.h"

typedef struct SNode *Stack;
#define MAXSIZE 10
#define ElementType int
struct SNode
{
	ElementType Data[MAXSIZE];
        //top is the number of elements
	int top;
};

//make a empty stack
Stack makeEmpty() {
	Stack S = (Stack)malloc(sizeof(struct SNode));
	S->top = 0;
}
//check is empty
bool isEmpty(Stack ptrs) {
	if (ptrs->top==0) {
		return true;
	}
	return false;
}
//check is full
bool isFull(Stack ptrs) {
	if (ptrs->top==MAXSIZE)
	{
		return true;
	}
	return false;
}
//push element
void push(ElementType value, Stack ptrs) {
	if (isFull(ptrs)) {
		printf("the stack has been full.");
		return ;
	}
	ptrs->Data[ptrs->top++] = value;
}
//pop
ElementType pop(Stack ptrs) {
	if (isEmpty(ptrs))
	{
		printf("the stack has been empty.");
		return;
	}
	return ptrs->Data[--ptrs->top];
}
int main() {
	Stack S = makeEmpty();
	//push 1,2,...5
	for (int i = 1; i < 6; i++) {
		push(i, S);
	}
	//pop all elements
	while (!isEmpty(S)) {
		printf("%d ", pop(S));
	}
	return 0;
}

对于用链表构造一个堆栈,那么栈顶应该是在链表的尾部还是头部?答案是都可以,栈顶在头部的话,入栈时,因为我们有空头节点的原因,直接建立一个新节点保存元素,将新节点的\(Next\)指向空头结点的\(Next\),再把空头结点的\(Next\)指向新节点。出栈用一个临时指针(\(temp\))指向空头结点的\(Next\),再将空头结点的\(Next\)指向\(temp\)指向节点的\(Next\),这样就将需要抛出的元素从链表中取出,保存元素值,释放掉该节点(\(free\)),返回要抛出的元素;栈顶在尾部的话,入栈时,因为我们有空头节点的原因,无需考虑链表空和不空状态下的不同操作,直接用指针遍历到最后一个元素,建立一个新起点保存的元素,然后把它接在列表的末尾。出栈时,我们可以遍历的方法,直到\(ptrs->Next->Next\)\(NULL\)时,此时\(ptrs\)所指的正好是栈顶的第二个元素,保证了不会出现抛出后无法回去(如果直接遍历到栈顶元素会无法找到栈顶元素的上一个节点,无法将其的\(Next\)设为\(NULL\),这将会导致错误),用一个临时指针指向\(ptrs->Next\)(也就是栈顶元素的节点),保存元素的值,然后释放掉该节点,将\(ptrs\)指向的节点\(Next\)设为\(NULL\),返回需要抛出元素的值。(注意:栈顶在尾部,堆栈一定要有空头节点,否则实现起来将会极其困难复杂)

虽然栈顶在头部或者尾部都可以,但还是建议栈顶设置在在头部(从算法上看在头部相比在尾部会更快)。

//The top of the stack is at the head of the list
#include<stdio.h>
#include<stdbool.h>
#include "malloc.h"

typedef struct SNode* Stack;
#define ElementType int
struct SNode
{
	ElementType Data;
	Stack Next;
};

//get link stack length,the empty stack has a header, the default length is 0
int length(Stack ptrs) {
	Stack temp = ptrs;
	int len = 0;
	while (temp->Next) {
		temp = temp->Next;
		len++;
	}
	return len;
}
//make an empty linked Stack,generate an empty header(length is 1)
Stack makeEmpty() {
	Stack ptrs;
	ptrs = (Stack)malloc(sizeof(struct SNode));
	ptrs->Next = NULL;
	return ptrs;
}
//check the linklist is empty
bool isEmpty(Stack ptrs) {
	if (length(ptrs) == 0) {
		return true;
	}
	else {
		return false;
	}
}
//push
Stack push(ElementType value, Stack ptrs) {
	Stack newLNode = (Stack)malloc(sizeof(struct SNode));
	newLNode->Data = value;
	newLNode->Next = ptrs->Next;
	ptrs->Next = newLNode;
	return ptrs;
}
//pop
ElementType pop(Stack ptrs) {
	if (isEmpty(ptrs)) {
		printf("the Stack has been empty.");
		return -1;
	}
	Stack temp = ptrs->Next;
	ElementType value = temp->Data;
	ptrs->Next = temp->Next;
	free(temp);
	return value;
}
//print Stack
void printStack(Stack ptrs) {
	if (isEmpty(ptrs)) {
		return;
	}
	Stack temp = ptrs->Next;
	while (temp) {
		printf("%d ", temp->Data);
		temp = temp->Next;
	}
	printf("\n");
}
int main() {
	Stack S = makeEmpty();
	for (int i = 0; i < 5; i++) {
		ElementType value;
		scanf_s("%d", &value);
		S = push(value, S);
	}
	printStack(S);
	while (!isEmpty(S)) {
		printf("%d ", pop(S));
	}
	return 0;
}
//The top of the stack is at the tail of the list
#include<stdio.h>
#include<stdbool.h>
#include "malloc.h"

typedef struct SNode* Stack;
#define ElementType int
struct SNode
{
	ElementType Data;
	Stack Next;
};

//get link stack length,the empty stack has a header, the default length is 0
int length(Stack ptrs) {
	Stack temp = ptrs;
	int len = 0;
	while (temp->Next) {
		temp = temp->Next;
		len++;
	}
	return len;
}
//make an empty linked Stack,generate an empty header(length is 1)
Stack makeEmpty() {
	Stack ptrs;
	ptrs = (Stack)malloc(sizeof(struct SNode));
	ptrs->Next = NULL;
	return ptrs;
}
//check the linklist is empty
bool isEmpty(Stack ptrs) {
	if (length(ptrs) == 0) {
		return true;
	}
	else {
		return false;
	}
}
//push
Stack push(ElementType value, Stack S) {
	Stack newLNode = (Stack)malloc(sizeof(struct SNode));
	newLNode->Data = value;
	newLNode->Next = NULL;
	Stack ptrs = S;
	while (ptrs->Next) {
		ptrs = ptrs->Next;
	}
	ptrs->Next = newLNode;
	return S;
}
//pop
ElementType pop(Stack S) {
	if (isEmpty(S)) {
		printf("the Stack has been empty.");
		return -1;
	}
	Stack ptrs = S;
	while (ptrs->Next->Next) {
		ptrs = ptrs->Next;
	}
	Stack temp = ptrs->Next;
	ElementType value = temp->Data;
	ptrs->Next = NULL;
	free(temp);
	return value;
}
//print Stack
void printStack(Stack ptrs) {
	if (isEmpty(ptrs)) {
		return;
	}
	Stack temp = ptrs->Next;
	while (temp) {
		printf("%d ", temp->Data);
		temp = temp->Next;
	}
	printf("\n");
}
int main() {
	Stack S = makeEmpty();
	for (int i = 0; i < 2; i++) {
		ElementType value;
		scanf_s("%d", &value);
		S = push(value, S);
	}
	printStack(S);
	while (!isEmpty(S)) {
		printf("%d ", pop(S));
	}
	return 0;
}

队列

队列,顾名思义就是像排队一样,先来排队的人先排到,队列具有先进先出后进后出的特性。同样可以通过数组或者链表实现,下面给出实现代码。

//implements by array
#include<stdio.h>
#include<stdbool.h>
#include"malloc.h"

#define ElementType int
#define MAXSIZE 10

typedef struct QNode* Queue;
struct QNode
{
	ElementType Data[MAXSIZE];
	int front;
	int rear;
};

Queue makeempty() {
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->front = 0;
	Q->rear = 0;
	return Q;
}
void QueueAdd(ElementType value, Queue ptrq) {
	if ((ptrq->rear + 1) % MAXSIZE == ptrq->front) {
		printf("The quque has been full.");
		return;
	}
	ptrq->rear = (++ptrq->rear) % MAXSIZE;
	ptrq->Data[ptrq->rear] = value;
}

ElementType QueueDelete(Queue ptrq) {
	if (ptrq->front == ptrq->rear) {
		printf("The queue has been empty.");
		return -1;
	}
	ptrq->front = (++ptrq->front) % MAXSIZE;
	return ptrq->Data[ptrq->front];
}
int main(void) {
	Queue Q = makeempty();
	for (int i = 1; i < 10;i++) {
		ElementType value;
		scanf_s("%d", &value);
		QueueAdd(value,Q);
	}
	QueueDelete(Q);
	QueueAdd(10, Q);
	return 0;
}
//implements by linklist
#include<stdio.h>
#include<stdlib.h>

#define ElementType int
typedef struct QNode* Queue;
struct QNode
{
	ElementType Data;
	Queue Next;
};

Queue makeEmpty() {
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->Next = NULL;
	return Q;
}

void QueueAdd(ElementType value, Queue Q) {
	Queue temp = Q->Next;
	Queue newNode = (Queue)malloc(sizeof(struct QNode));
	newNode->Data = value;
	newNode->Next = temp;
	Q->Next = newNode;
}

ElementType QueueDelete(Queue Q) {
	Queue ptrq = Q;
	if (!ptrq->Next) {
		printf("The queue has been empty.");
		return -1;
	}
	while (ptrq->Next->Next) {
		ptrq = ptrq->Next;
	}
	Queue temp = ptrq->Next;
	ptrq->Next = NULL;
	ElementType value = temp->Data;
	free(temp);
	return value;
}

int main(void) {
	Queue Q = makeEmpty();
	for (int i = 1; i < 5; i++) {
		ElementType value;
		scanf_s("%d", &value);
		QueueAdd(value, Q);
	}
	QueueDelete(Q);
	QueueAdd(5, Q);
	return 0;
}

课后练习题(4个小题)

02-线性结构1 两个有序链表序列的合并 (15point(s))

本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个非递减的整数序列。
函数接口定义:

List Merge( List L1, List L2 );

其中List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

L1和L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1和L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType Data;
    PtrToNode   Next;
};
typedef PtrToNode List;

List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表;空链表将输出NULL */

List Merge( List L1, List L2 );

int main()
{
    List L1, L2, L;
    L1 = Read();
    L2 = Read();
    L = Merge(L1, L2);
    Print(L);
    Print(L1);
    Print(L2);
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

3
1 3 5
5
2 4 6 8 10

输出样例:

1 2 3 4 5 6 8 10
NULL
NULL

代码:

#include <stdio.h>
#include <stdlib.h>
#include"malloc.h"

typedef int ElementType;
typedef struct Node* PtrToNode;

struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List;

List Read(); /* 细节在此不表 */
void Print(List L); /* 细节在此不表;空链表将输出NULL */

List Merge(List L1, List L2);

int main()
{
    List L1, L2, L;
    L1 = Read();
    L2 = Read();
    L = Merge(L1, L2);
    Print(L);
    Print(L1);
    Print(L2);
    return 0;
}
List Read() {
    //申请一块空间储存l,初始的最后一位是0
    List L = (List)malloc(sizeof(struct Node));
    L->Next = NULL;
    List ptrl = L;
    //要读多少个数?
    int num;
    scanf_s("%d", &num);
    //逐个读入,读入的同时增大最后一位的位置。
	for (int i = 0; i < num;i++) {
		ElementType value;
		scanf_s("%d", &value);
		List newLNode = (List)malloc(sizeof(struct Node));
		newLNode->Data = value;
        newLNode->Next = NULL;
        ptrl->Next = newLNode;
        ptrl = ptrl->Next;
	}
    return L;
}

void Print(List L) {
    int isfrist = 1;
    List ptrl = L->Next;
    if (ptrl == NULL) {
        printf("NULL\n");
        return;
    }
    else {
        while (ptrl)
        {
            if (isfrist) {
                printf("%d", ptrl->Data);
                isfrist = 0;
            }
            else {
                printf(" %d", ptrl->Data);
            }
            ptrl = ptrl->Next;
        }
        printf("\n");
    }
    return;
}
List Merge(List L1,List L2) {
    //存储合并后的链表
    List L = (List)malloc(sizeof(struct Node));
    //三个指针分别用于遍历l1和l2和L
    List ptrl1 = L1->Next, ptrl2 = L2->Next,ptrl = L;
    //两个链表都不空时,进行循环比较,其中任意一方空则退出
    while (ptrl1 && ptrl2) {
        //ptrl1指向的数据比ptrl2时,将其
        if (ptrl1->Data < ptrl2->Data) {
            ptrl->Next = ptrl1;
            ptrl1 = ptrl1->Next;
        }
        else {
            ptrl->Next = ptrl2;
            ptrl2 = ptrl2->Next;
        }
        ptrl = ptrl->Next;
    }
    //如果链表1空了,将现在未处理的链表2接到l末位,列表2空了同理.....
    if (ptrl1==NULL) {
        ptrl->Next = ptrl2;
    }
    if (ptrl2==NULL) {
        ptrl->Next = ptrl1;
    }
    //将l1和l2指向为null
    L1->Next = NULL;
    L2->Next = NULL;
    //将合并后的链表返回
    return L;
}

02-线性结构2 一元多项式的乘法与加法运算 (20point(s))

设计函数分别求两个一元多项式的乘积与和。

输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。

输入样例:

4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

代码:

#include<stdio.h>
#include<stdbool.h>
#include "malloc.h"

typedef struct Node* List;
#define ElementType int
struct Node
{
	ElementType Coef;
	ElementType Degree;
	List Next;
};

List Read() {
	//申请一块空间储存l,初始的最后一位是0
	List L = (List)malloc(sizeof(struct Node));
	L->Next = NULL;
	List ptrl = L;
	//要读多少个数?
	int num;
	scanf_s("%d", &num);
	//逐个读入,读入的同时增大最后一位的位置。
	for (int i = 0; i < num; i++) {
		ElementType coef;
		ElementType degree;
		scanf_s("%d", &coef);
		scanf_s("%d", &degree);
		List newLNode = (List)malloc(sizeof(struct Node));
		newLNode->Coef = coef;
		newLNode->Degree = degree;
		newLNode->Next = NULL;
		ptrl->Next = newLNode;
		ptrl = ptrl->Next;
	}
	return L;
}
//print List
void printList(List ptrl) {
	if (!ptrl->Next) {
		printf("0 0\n");
		return;
	}
	int isfrist = 1;
	List temp = ptrl->Next;
	while (temp)
	{
		if (isfrist) {
			printf("%d %d", temp->Coef, temp->Degree);
			isfrist = 0;
		}
		else {
			printf(" %d %d", temp->Coef, temp->Degree);
		}
		temp = temp->Next;
	}
	printf("\n");
}
//按从大到小的排序插入
List insert(List newNode, List L) {
	List ptrl = L;
	//如果l是空的则直接插入
	if (ptrl->Next == NULL) {
		ptrl->Next = newNode;
	}
	else {
		while (ptrl->Next && newNode->Degree < ptrl->Next->Degree) {
			ptrl = ptrl->Next;
		}
		if (ptrl->Next == NULL) {
			ptrl->Next = newNode;
		}
		//两个多项式的次方相同,合并他们。
		else if (ptrl->Next->Degree == newNode->Degree) {
			//如果节点合并后系数为0,删除该节点
			if (newNode->Coef + ptrl->Next->Coef == 0) {
				List temp = ptrl->Next;
				ptrl->Next = temp->Next;
				free(temp);
				free(newNode);
			}
			else {
				ptrl->Next->Coef += newNode->Coef;
			}
		}
		//ptrl所指向的下一个节点的次方小于新节点,将新结点插入在ptrl和它下一个节点之间。
		else {
			List temp = ptrl->Next;
			ptrl->Next = newNode;
			newNode->Next = temp;
		}
	}
	return L;
}
List Polynomialmultiplication(List L1, List L2) {
	//存储合并后的链表
	List L = (List)malloc(sizeof(struct Node));
	L->Next = NULL;
	//三个指针分别用于遍历l1和l2
	List ptrl1 = L1->Next, ptrl2 = L2->Next;
	//两个链表都不空时,进行乘法运算,其中任意一方空则退出
	if (ptrl1 == NULL || ptrl2 == NULL) {
		return L;
	}
	//循环至两个列表都空
	while (ptrl1) {
		while (ptrl2) {
			List newNode = (List)malloc(sizeof(struct Node));
			newNode->Coef = ptrl1->Coef * ptrl2->Coef;
			newNode->Degree = ptrl1->Degree + ptrl2->Degree;
			newNode->Next = NULL;
			L = insert(newNode, L);
			ptrl2 = ptrl2->Next;
		}
		ptrl2 = L2->Next;
		ptrl1 = ptrl1->Next;
	}
	return L;
}
List Polynomialaddition(List L1, List L2) {
	//存储合并后的链表
	List L = (List)malloc(sizeof(struct Node));
	//三个指针分别用于遍历l1和l2和L
	List ptrl1 = L1->Next, ptrl2 = L2->Next, ptrl = L;
	//两个链表都不空时,进行乘法运算,其中任意一方空则退出
	while (ptrl1 && ptrl2) {
		//建立一个新的节点。
		List newNode = (List)malloc(sizeof(struct Node));
		newNode->Next = NULL;
		//ptrl1指向的数据比ptrl2大时,将其复制添加到l末
		if (ptrl1->Degree > ptrl2->Degree) {
			newNode->Coef = ptrl1->Coef;
			newNode->Degree = ptrl1->Degree;
			ptrl->Next = newNode;
			ptrl1 = ptrl1->Next;
			ptrl = ptrl->Next;
		}
		//ptrl2指向的数据比ptrl1大时,将其复制添加到l末
		else if (ptrl1->Degree < ptrl2->Degree) {
			newNode->Coef = ptrl2->Coef;
			newNode->Degree = ptrl2->Degree;
			ptrl->Next = newNode;
			ptrl2 = ptrl2->Next;
			ptrl = ptrl->Next;
		}
		//ptrl2指向的数据和ptrl1一样大时,储存他们的和后添加到L
		else {
			//如果系数不为0的添加,否则将释放该节点。
			ElementType newcoef = ptrl1->Coef + ptrl2->Coef;
			if (newcoef) {
				newNode->Coef = ptrl1->Coef + ptrl2->Coef;
				newNode->Degree = ptrl1->Degree;
				ptrl->Next = newNode;
				ptrl = ptrl->Next;
			}
			else {
				free(newNode);
			}
			ptrl1 = ptrl1->Next;
			ptrl2 = ptrl2->Next;
		}
	}
	//如果链表1空了,将现在未处理的链表2接到l末位,列表2空了同理.....
	if (ptrl1 == NULL) {
		ptrl->Next = ptrl2;
	}
	if (ptrl2 == NULL) {
		ptrl->Next = ptrl1;
	}
	//将合并后的链表返回
	return L;
}

int main(void) {
	List L1, L2;
	L1 = Read();
	L2 = Read();
	List L4 = Polynomialmultiplication(L1, L2);
	printList(L4);
	List L3 = Polynomialaddition(L1, L2);
	printList(L3);
	return 0;
}

02-线性结构3 Reversing Linked List (25point(s))

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.

Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤\(10 ​^5\)) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

\(Address\) \(Data\) \(Next\)

where \(Address\) is the position of the node, \(Data\) is an integer, and \(Next\) is the position of the next node.

Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

代码:

#include<stdio.h>
#include<stdlib.h>

typedef struct Node* List;
struct Node
{
	int Address;
	int Data;
	int Next;
	List link;
};
//获取链表长度,因为N只是输入节点而非有效节点
int length(List ptrl) {
	List temp = ptrl;
	int len = 0;
	while (temp->link) {
		temp = temp->link;
		len++;
	}
	return len;
}
//将对应地址的节点从链表删除,并且返回回来准备重新插入
List returnInValue(int value, List L) {
	List temp = L;
	while (temp->link)
	{
		if (temp->link->Address == value) {
			break;
		}
		temp = temp->link;
	}
	List key = temp->link;
	temp->link = key->link;
	key->link = NULL;
	return key;
}
//读取并排序
List Read(int firstAddress,int N,int K) {
	List L1 = (List)malloc(sizeof(struct Node));
	L1->link = NULL;
	List ptrl = L1;
	//将节点存入链表L1
	for(int i = 0;i < N;i++)
	{
		int Address, Data, Next;
		scanf_s("%d %d %d",&Address,&Data,&Next);
		List newnode = (List)malloc(sizeof(struct Node));
		newnode->Address = Address;
		newnode->Data = Data;
		newnode->Next = Next;
		newnode->link = NULL;
		ptrl->link = newnode;
		ptrl = ptrl->link;
	}
	//根据节点中的地址和下一个排序,将排好序的存在L2(因为有可能有些节点是无效的)
	List L2 = (List)malloc(sizeof(struct Node));
	L2->link = NULL;
	List ptrl2 = L2;
	int findaddress = firstAddress;
	while (findaddress!=-1) {
		List key = returnInValue(findaddress, L1);
		key->link = ptrl2->link;
		ptrl2->link = key;
		findaddress = key->Next;
		ptrl2 = ptrl2->link;
	}
	return L2;
}
//根据第几个来返回节点
List returnInIndex(int index, List L) {
	List temp = L;
	for (int i = 1; i < index; i++) {
		temp = temp->link;
	}
	List key = temp->link;
	temp->link = key->link;
	key->link = NULL;
	return key;
}
//反转链表并且将反转后的链表节点中的Next调整正常
List specialsort(List L,int N,int K) {
	//如果K=1,不用反转,反转后也一样
	if (K == 1) {
		return L;
	}
	//建立新表头
	List finalList = (List)malloc(sizeof(struct Node));
	finalList->link = NULL;
	List ptrfl = finalList;
	//直到把L中所有的节点搬走后结束
	int num = N - (N % K);
	int index = K;
	//先把需要反转的搬走
	for (int i = 0; i < num; i++) {
		List node = returnInIndex(index--,L);
		ptrfl->link = node;
		ptrfl->Next = node->Address;
		ptrfl = ptrfl->link;
		if (index == 0) {
			index = K;
		}
	}
	//再将无需翻转的接到finalList,别忘了当前ptrfl指向的节点,Next的值还没有修改。
	if (L->link) {
		ptrfl->Next = L->link->Address;
		ptrfl->link = L->link;
	}
	//将ptrfl指向最后一个节点,把他的next值改为-1。
	while (ptrfl->link) {
		ptrfl =  ptrfl->link;
	}
	ptrfl->Next = -1;
	return finalList;
}
void printList(List L) {
	List ptrl = L->link;
	while (ptrl) {
		printf("%05d %d ", ptrl->Address, ptrl->Data);
		if (ptrl->Next == -1) {
			printf("%d\n", ptrl->Next);
		}
		else {
			printf("%05d\n", ptrl->Next);
		}
		ptrl = ptrl->link;
	}
}
int main(void) {
	int firstAddress, N, K;
	scanf_s("%d %d %d", &firstAddress, &N, &K);
	//用于读取节点并按照格式排序
	List readList = Read(firstAddress, N, K);
	//存储反转后的链表
	List finalList = specialsort(readList,length(readList) ,K);
	//按照格式打印
	printList(finalList);
	return 0;
}

02-线性结构4 Pop Sequence (25point(s))

Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, ..., N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.

Input Specification:
Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.

Output Specification:
For each pop sequence, print in one line "YES" if it is indeed a possible pop sequence of the stack, or "NO" if not.

Sample Input:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

Sample Output:

YES
NO
NO
YES
NO

代码:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include "malloc.h"

typedef struct SNode* Stack;
#define MAXSIZE 1000
#define ElementType int
struct SNode
{
	ElementType Data[MAXSIZE];
	int top;
};
//make a empty stack
Stack makeEmpty() {
	Stack S = (Stack)malloc(sizeof(struct SNode));
	S->top = 0;
	return S;
}
//check is empty
bool isEmpty(Stack ptrs) {
	if (ptrs->top == 0) {
		return true;
	}
	return false;
}
//check is full
bool isFull(Stack ptrs,int Max) {
	if (ptrs->top == Max+1)
	{
		return true;
	}
	return false;
}
//push element
void push(ElementType value, Stack ptrs) {
	ptrs->Data[ptrs->top++] = value;
}
//pop
ElementType pop(Stack ptrs) {
	ptrs->top = ptrs->top - 1;
	return ptrs->Data[ptrs->top];
}
int main(void) {
	int M, N, K;
	scanf_s("%d %d %d", &M, &N, &K);
	//读取K次
	for (int i = 0; i < K; i++) {
		//默认是合法,检测到异常再定义为不合法
		bool isright = true;
		//建一个空堆栈
		Stack S = makeEmpty();
		//将出栈顺序保存
		int array[1001];
		for (int i = 0; i < N; i++) {
			scanf_s("%d", &array[i]);
		}
		//index对应array下标,直到遍历完成且中途没有发生不合理的事说明合法
		int index = 0;
		int num = 0;//num为压栈的次数
		while (index != N) {
			//如果下标所指的值大于目前压栈的次数,压栈
			if (num < array[index]) {
				while (num < array[index]) {
					push(++num, S);
					//每次压过判断是否满了(大于N)
					if (isFull(S,M))
					{
						isright = false;
						goto LOOP_VAL;
					}
				}
				//抛出并检查是否一样
				pop(S);
			}
			//如果下标所指的值小于目前压栈的次数,出栈
			else {
				//如果出栈的节点不为当前下标所指的值,说明有问题
				int temp = pop(S);
				if (temp != array[index]) {
					isright = false;
					break;
				}
			}
			index++;
		}
		LOOP_VAL: //标号 
		if (isright) {
			printf("YES\n");
		}
		else {
			printf("NO\n");
		}
	}
}
posted @ 2020-08-22 16:00  W&B  阅读(255)  评论(0编辑  收藏  举报