數據結構第二節(基本數據結構)

基本數據結構

在本節中,將會介紹關於數據結構的基本類型,如線性表,堆棧和隊列node

線性表

在數據結構中,線性表是最多見也是使用最頻繁的基本數據結構,它能夠經過數組實現或者鏈表實現,下面給出兩種不一樣的實現代碼。git

//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\),返回須要拋出元素的值。(注意:棧頂在尾部,堆棧必定要有空頭節點,不然實現起來將會極其困難複雜)數據結構

雖然棧頂在頭部或者尾部均可以,但仍是建議棧頂設置在在頭部(從算法上看在頭部相比在尾部會更快)。less

//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;
}

隊列

隊列,顧名思義就是像排隊同樣,先來排隊的人先排到,隊列具備先進先出後進後出的特性。一樣能夠經過數組或者鏈表實現,下面給出實現代碼。dom

//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結構定義以下:this

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");
		}
	}
}
相關文章
相關標籤/搜索