PAT
leetcode
代码github备份
/*
Created by salmon on 2021-9-14 21:27.
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
struct ListNode head;
struct ListNode* res = &head;
while (l1 != NULL && l2 != NULL) { //l2小于等于l1时插入l2,否则插入l1; 每次插入后指针后移一位;
if(l2 -> val <= l1 -> val){
res -> next = l2;
l2 = l2 -> next;
} else {
res -> next = l1;
l1 = l1 -> next;
}
res = res -> next;
}
//此时循环结束,必定至少有一个链表被循环到最后一个节点之后的空指针上
if(l1 == NULL){
res -> next = l2;
} else if (l2 == NULL){
res -> next = l1;
}
//返回头指针
//不能返回head->next,因为head不是指针是一个struct类型的变量
//参考文档:https://blog.csdn.net/faihung/article/details/79190039
return head.next;
}
/*
Created by salmon on 2021-9-13 23:09.
单链表逆转
*/
typedef struct Node *PtrToNode;
struct Node {
ElementType Data; /* 存储结点数据 */
PtrToNode Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */
#include
#include
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表 */
List Reverse( List L );
int main()
{
List L1, L2;
L1 = Read();
L2 = Reverse(L1);
Print(L1);
Print(L2);
return 0;
}
/* 你的代码将被嵌在这里 */
List Reverse( List L ){
if(L==NULL || L->Next==NULL)
return L;
//需要三个指针,顺序为L,P1,P2
//L指向L的头结点,并且为了实现目的将其孤立
//p1指向L的下一个,p2指向p1的下一个,所以必定是p2先指向NULL
List p1 = L->Next;
L->Next = NULL;
List p2 = p1->Next;
while (p2) {
//调转指针next方向
p1->Next = L;
//第一个指针后移一位
L = p1;
//第二个指针后移一位
p1 = p2;
第三个指针后移一位
p2 = p2->Next;
}
//处理到这里时面临一种情况:L在倒数第二个节点,P1在倒数第一个结点,P2在空结点上
//此时最后的P1结点没有处理,应该讲P1的next也逆转
p1->Next = L;
return p1;
}
/**
*Created by salmon on 2021-9-14 22:25.
**/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
if(head == NULL){ //若为空必定不存在环
return false;
}
struct ListNode* fast = head -> next;
struct ListNode* slow = head;
//快慢指针,快的比慢的快一个位置
//如果快的追上慢的就表明有环
while (slow != fast) {
if(fast == NULL || fast -> next == NULL){
//因为fast一次移动两个元素,所以fast至少指向该链表倒数第二个节点
//否则会发生空指针访问空指针域的问题
return false;
}
fast = fast -> next -> next;
slow = slow -> next;
}
return true;
}
/**
*Created by salmon on 2021-9-14 23:32.
**/
/**
*Created by salmon on 2021-9-14 22:57.
**/
#include
#include
#define MAXSIZE 7
#define ERROR -1
typedef enum {false, true} bool;
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P;
int N;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
if ( Insert(L, X, 0)==false )
printf(" Insertion Error: %d is not in.\n", X);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else
printf("%d is at position %d.\n", X, P);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &P);
if ( Delete(L, P)==false )
printf(" Deletion Error.\n");
if ( Insert(L, 0, P)==false )
printf(" Insertion Error: 0 is not in.\n");
}
return 0;
}
/* 你的代码将被嵌在这里 */
List MakeEmpty(){ //创建并返回一个空的线性表
List list = (List)malloc(sizeof(struct LNode));
list->Last = -1;
return list;
}
Position Find( List L, ElementType X ){ //返回线性表中X的位置。若找不到则返回ERROR;
for (int i = 0; i <= L->Last; ++i) {//TODO 这里可能错
if(L->Data[i] == X){
return i;
}
}
return ERROR;
}
bool Insert( List L, ElementType X, Position P ){ // 将X插入在位置P并返回true。若空间已满,则打印“FULL”并返回false;如果参数P指向非法位置,则打印“ILLEGAL POSITION”并返回false;
if(P < 0 || P > L->Last + 1){ //非法位置,正确:可以插入在[0,当前数组最大值+1]之间
printf("ILLEGAL POSITION");
return false;
}
if(L->Last == MAXSIZE - 1){ //顺序表已满
printf("FULL");
return false;
}
for (int i = L->Last + 1; i > P ; --i) { //i一直遍历到要插入下标P+1的位置
L->Data[i] = L->Data[i - 1];
}
//当前P位置空缺出来
L->Data[P] = X;
//更新最后一个结点的下标
L->Last++;
return true;
}
bool Delete( List L, Position P ){// 将位置P的元素删除并返回true。若参数P指向非法位置,则打印“POSITION P EMPTY”(其中P是参数值)并返回false。
if(P < 0 || P > L->Last){ //非法位置,正确:可以删除在[0,当前数组最大值]之间的任何数
printf("POSITION %d EMPTY",P);
return false;
}
for (int i = P; i < L->Last ; ++i) { //i一直遍历到数组倒数第二个元素
L->Data[i] = L->Data[i + 1];
}
L->Data[L->Last] = -1; //去掉最后一个元素
L->Last--;
return true;
}
/**
*Created by salmon on 2021-9-15 22:15.
**/
#include
#include
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode List;
List Read(); /* 细节在此不表 */
int Length( List L );
int main()
{
List L = Read();
printf("%d\n", Length(L));
return 0;
}
/* 你的代码将被嵌在这里 */
int Length( List L ){
int length = 0;
while (L) {
length++;
L = L->Next;
}
return length;
}
/**
*Created by salmon on 2021-9-15 22:21.
**/
#include
#include
#define ERROR -1
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode List;
List Read(); /* 细节在此不表 */
ElementType FindKth( List L, int K );
int main()
{
int N, K;
ElementType X;
List L = Read();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &K);
X = FindKth(L, K);
if ( X!= ERROR )
printf("%d ", X);
else
printf("NA ");
}
return 0;
}
/* 你的代码将被嵌在这里 */
ElementType FindKth( List L, int K ){ //这里的K不是下标,是序号
if(K <= 0) return ERROR;
int index = 0;
while (L) {
if (index + 1 == K) {
return L->Data;
} else {
L = L->Next;
index++;
}
}
return ERROR;
}
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* res = malloc(sizeof(struct ListNode));
res -> next = head;//虚拟一个空的头结点出来
struct ListNode* p = res;//拷贝res,用p进行遍历,保证无论如何删除使res的下一个就是头结点,如果不拷贝res而是使用head返回,那么如果删除第一个元素就会出现问题
// while (p) { 这里如果不是下面这样写的话,会出现访问空指针空间的异常
while (p->next != NULL) {
if(p -> next -> val == val) {
p->next = p->next->next;
} else {
p = p -> next;
}
}
return res->next;
}
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* deleteDuplicates(struct ListNode* head){
if(head == NULL || head->next == NULL){
return head;
}
struct ListNode* p = head;
while (p->next != NULL) {
if(p->next->val == p->val){
p->next = p->next->next;
} else {
p = p->next;
}
}
return head;
}
/**
*Created by salmon on 2021-9-16 22:07.
**/
#include
#include
#define ERROR NULL
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
Position Find( List L, ElementType X );
List Insert( List L, ElementType X, Position P );
List Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P, tmp;
int N;
L = NULL;
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
L = Insert(L, X, L);
if ( L==ERROR ) printf("Wrong Answer\n");
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else {
L = Delete(L, P);
printf("%d is found and deleted.\n", X);
if ( L==ERROR )
printf("Wrong Answer or Empty List.\n");
}
}
L = Insert(L, X, NULL);
if ( L==ERROR ) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
tmp = Insert(L, X, P);
if ( tmp!=ERROR ) printf("Wrong Answer\n");
tmp = Delete(L, P);
if ( tmp!=ERROR ) printf("Wrong Answer\n");
for ( P=L; P; P = P->Next ) printf("%d ", P->Data);
return 0;
}
/* 你的代码将被嵌在这里 */
Position Find( List L, ElementType X ){//返回线性表中首次出现X的位置。若找不到则返回ERROR;
Position res = L;
while (L) {
if(L->Data == X){
return res;
} else {
L = L->Next;
res = res->Next;
}
}
return ERROR;
}
List Insert( List L, ElementType X, Position P ){ //将X插入在位置P指向的结点之前,返回链表的表头。如果参数P指向非法位置,
// 则打印“Wrong Position for Insertion”,返回ERROR;
if(P < 0) {
printf("Wrong Position for Insertion\n");
return ERROR;
}
struct LNode *head = malloc(sizeof(struct LNode));
head->Next = L;
struct LNode *p = head;
Position x = (Position)malloc(sizeof(struct LNode));
x->Data = X;
while (p) {
if(p->Next == P){//P为没有加入一个虚拟的头结点的第一个结点下标 也可以这么想i指向-1,p指向0; 但使i=0时i总是在p前面一个位置
struct LNode *temp = p->Next;
p->Next = x;
x->Next = temp;
return head->Next;
} else {
p = p->Next;
}
}
printf("Wrong Position for Insertion\n");
return ERROR;
}
List Delete( List L, Position P ){ //将位置P的元素删除并返回链表的表头。若参数P指向非法位置,
// 则打印“Wrong Position for Deletion”并返回ERROR
if(P < 0) {
printf("Wrong Position for Deletion\n");
return ERROR;
}
struct LNode *head = malloc(sizeof(struct LNode));
head->Next = L;
struct LNode *p = head;
while (p) {
if (p->Next == P) {
p->Next = p->Next->Next;
return head->Next;
} else {
p = p->Next;
}
}
printf("Wrong Position for Deletion\n");
return ERROR;
}
/**
*Created by salmon on 2021-9-17 22:05.
**/
#include
#include
#define ERROR NULL
typedef enum {false, true} bool;
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );
int main()
{
List L;
ElementType X;
Position P;
int N;
bool flag;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
flag = Insert(L, X, L->Next);
if ( flag==false ) printf("Wrong Answer\n");
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else {
flag = Delete(L, P);
printf("%d is found and deleted.\n", X);
if ( flag==false )
printf("Wrong Answer.\n");
}
}
flag = Insert(L, X, NULL);
if ( flag==false ) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
flag = Insert(L, X, P);
if ( flag==true ) printf("Wrong Answer\n");
flag = Delete(L, P);
if ( flag==true ) printf("Wrong Answer\n");
for ( P=L->Next; P; P = P->Next ) printf("%d ", P->Data);
return 0;
}
/* 你的代码将被嵌在这里 */
List MakeEmpty(){//创建并返回一个带头节点的空的线性表;
List list = (List)malloc(sizeof(struct LNode));
list->Next = NULL;
return list;
}
Position Find( List L, ElementType X ){// 返回线性表中X的位置。若找不到则返回ERROR;
Position p = L;
while (p->Next) {//至于这里为什么是p->Next是因为在下方的if中访问了p的下一个节点的内容,如果p的下一个节点为空,会发生段错误
if(p->Next->Data == X){
return p->Next;
} else {
p = p->Next;
}
}
return ERROR;
}
bool Insert( List L, ElementType X, Position P ){// 将X插入在位置P指向的结点之前,返回true。如果参数P指向非法位置,
// 则打印“Wrong Position for Insertion”,返回false;
Position p = L;
Position x = (Position)malloc(sizeof(struct LNode));
x->Data = X;
while (p) {
if(p->Next == P){
p->Next = x;
x->Next = P;
return true;
} else {
p = p->Next;
}
}
printf("Wrong Position for Insertion\n");
return false;
}
bool Delete( List L, Position P ){ // 将位置P的元素删除并返回true。若参数P指向非法位置,
// 则打印“Wrong Position for Deletion”并返回false。
Position p = L;
while (p) {
if(p->Next == P){
p->Next = p->Next->Next;
return true;
} else {
p = p->Next;
}
}
printf("Wrong Position for Deletion\n");
return false;
}
/**
*Created by salmon on 2021-9-18 22:13.
**/
#include
#include
#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
struct SNode {
ElementType *Data;
Position Top1, Top2;
int MaxSize;
};
typedef struct SNode *Stack;
Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );
Operation GetOp(); /* details omitted */
void PrintStack( Stack S, int Tag ); /* details omitted */
int main()
{
int N, Tag, X;
Stack S;
int done = 0;
scanf("%d", &N);
S = CreateStack(N);
while ( !done ) {
switch( GetOp() ) {
case push:
scanf("%d %d", &Tag, &X);
if (!Push(S, X, Tag)) printf("Stack %d is Full!\n", Tag);
break;
case pop:
scanf("%d", &Tag);
X = Pop(S, Tag);
if ( X==ERROR ) printf("Stack %d is Empty!\n", Tag);
break;
case end:
PrintStack(S, 1);
PrintStack(S, 2);
done = 1;
break;
}
}
return 0;
}
/* 你的代码将被嵌在这里 */
Stack CreateStack( int MaxSize ){//两端各有一个栈
Stack s = (Stack) malloc(sizeof(struct SNode));
s->Data = (ElementType *) malloc(sizeof(ElementType)*MaxSize);
s->MaxSize = MaxSize;
s->Top1 = -1;
s->Top2 = MaxSize;
return s;
}
bool Push( Stack S, ElementType X, int Tag ){//tag表示对哪个栈进行处理
if (S->Top1 + 1 == S->Top2) {
printf("Stack Full\n");
return false;
}
if(Tag == 1){
S->Top1++;
S->Data[S->Top1] = X;
} else {
S->Top2--;
S->Data[S->Top2] = X;
}
return true;
}
ElementType Pop( Stack S, int Tag ){
if ((S->Top1 == -1 && Tag == 1) || (S->Top2 == S->MaxSize && Tag == 2)) {
printf("Stack %d Empty\n",Tag);
return ERROR;
}
if(Tag == 1){
return S->Data[S->Top1--];
} else {
return S->Data[S->Top2++];
}
}
int GetHeight( BinTree BT ){ //在脑中想象一颗只有2层的满二叉树可以更好地理解
int maxLeft = 0,maxRight = 0;
if(BT == NULL){ //第一次,一直递归到此树叶子结点的孩子结点时停止,此时该结点为NULL所以高度为0
return 0;
} else { //以当前BT为根节点判断左子树高度和右子树高度谁更大
maxLeft = GetHeight(BT->Left);
maxRight = GetHeight(BT->Right);
return (maxLeft > maxRight ? maxLeft + 1 : maxRight + 1); //此时已经计算完成一个叶结点,返回结点到它的双亲节点,显然高度要加1
}
}
非递归算法求二叉树的高度,一般利用层次遍历的方法,初始化一个队列,定义一个中间变量来保存每次循环一开始的rear,如果front追上了rear则二叉树高度加1
int GetHeight( BinTree BT ){ //在脑中想象一颗只有2层的满二叉树可以更好地理解
if (BT == NULL) return 0;
BinTree Queque[999];
//初始化队列
Queque[0] = BT;
int front = 0, rear = 1,last = rear;
int high = 0;
while (front < rear) {
if (Queque[front]->Left != NULL) {
Queque[rear] = Queque[front]->Left;
rear++;
}
if(Queque[front]->Right != NULL) {
Queque[rear] = Queque[front]->Right;
rear++;
}
front++;
if(front == last){
high++;
last = rear;
}
}
return high;
}
Position trueBinarySearch( List L, ElementType X, Position low, Position high ){
if(low > high) return NotFound;
Position mid = (Position)((low + high) / 2);
if (X < L->Data[mid]) {
return trueBinarySearch(L,X,low,mid - 1);
} else if (X > L->Data[mid]) {
return trueBinarySearch(L,X,mid + 1,high);
} else {
return mid;
}
}
Position BinarySearch( List L, ElementType X ){
Position high = L->Last;
Position low = 0;
return trueBinarySearch(L,X,low,high);
}
Position BinarySearch( List L, ElementType X ){
ElementType tag;
Position low = 0;
Position high = L -> Last;
while (low <= high) {
Position mid = (ElementType)((low + high) / 2);
if (X < L->Data[mid]) {
high = mid - 1;
} else if (X > L->Data[mid]) {
low = mid + 1;
} else {
return mid;
}
}
return NotFound;
}
void InorderTraversal( BinTree BT ){//中序
if (BT) {
InorderTraversal(BT->Left);
printf(" %c",BT->Data);
InorderTraversal(BT->Right);
}
}
void PreorderTraversal( BinTree BT ){
if (BT) {
printf(" %c",BT->Data);
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
}
void PostorderTraversal( BinTree BT ){
if (BT) {
PostorderTraversal(BT->Left);
PostorderTraversal(BT->Right);
printf(" %c",BT->Data);
}
}
void LevelorderTraversal( BinTree BT ){//层次遍历
if (BT == NULL) return;
BinTree Queque[999];
//初始化队列
Queque[0] = BT;
int front = 0, rear = 1;
while (front < rear) {
if (Queque[front]->Left != NULL) {
Queque[rear] = Queque[front]->Left;
rear++;
}
if(Queque[front]->Right != NULL) {
Queque[rear] = Queque[front]->Right;
rear++;
}
printf(" %c",Queque[front]->Data);
front++;
}
}
BinTree assistStack[999];
int assistTop = -1;
void assistPush( BinTree BT ){
if(assistTop >= 999) return;
assistTop++;
assistStack[assistTop] = BT;
}
BinTree assistPop(){
if(assistTop <= -1) return NULL;
return assistStack[assistTop--];
}
int assistStackIsEmpty(){
if(assistTop <= -1) return -1; //-1为空
else return 1; //1为不空
}
BinTree Stack[999];
int top = -1;
void push( BinTree BT ){
if(top >= 999) return;
top++;
Stack[top] = BT;
}
BinTree pop(){
if(top <= -1) return NULL;
return Stack[top--];
}
int stackIsEmpty(){
if(top <= -1) return -1; //-1为空
else return 1; //1为不空
}
void InorderTraversal( BinTree BT ){//中序
while (BT != NULL || stackIsEmpty() == 1) {
while (BT != NULL) {
push(BT);
BT = BT->Left;
}
if (stackIsEmpty() == 1) {
BT = pop();
printf(" %c",BT->Data);
BT = BT->Right;
}
}
}
void PreorderTraversal( BinTree BT ){
if(BT == NULL) return;
push(BT);
while (stackIsEmpty() == 1) {
BT = pop();
printf(" %c",BT->Data);
if(BT->Right != NULL){
push(BT->Right);
}
if(BT->Left != NULL){
push(BT->Left);
}
}
}
void PostorderTraversal( BinTree BT ){
while (BT != NULL || assistStackIsEmpty() == 1) {
while (BT != NULL) {
assistPush(BT);
push(BT);
BT = BT->Right;
}
if(assistStackIsEmpty() == 1){
BT = assistPop();
BT = BT->Left;
}
}
while (stackIsEmpty() == 1) {
BinTree res = pop();
printf(" %c",res->Data);
}
}
void LevelorderTraversal( BinTree BT ){//层次遍历
if (BT == NULL) return;
BinTree Queque[999];
//初始化队列
Queque[0] = BT;
int front = 0, rear = 1;
while (front < rear) {
if (Queque[front]->Left != NULL) {
Queque[rear] = Queque[front]->Left;
rear++;
}
if(Queque[front]->Right != NULL) {
Queque[rear] = Queque[front]->Right;
rear++;
}
printf(" %c",Queque[front]->Data);
front++;
}
}
参考博客:https://blog.csdn.net/dabusiGin/article/details/102736180?spm=1001.2014.3001.5501
这里我们总结一下非递归版本的二叉树遍历:
总的来说就是,前中后非递归遍历要利用好栈,用栈来代替递归中的回溯到父节点的功能。
/**
*Created by salmon on 2021-9-23 22:22.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree CreatBinTree(); /* 实现细节忽略 */
void PreorderPrintLeaves( BinTree BT );
int main()
{
BinTree BT = CreatBinTree();
printf("Leaf nodes are:");
PreorderPrintLeaves(BT);
printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
void PreorderPrintLeaves( BinTree BT ){
if(!BT) return;
if(BT->Left == NULL && BT->Right == NULL){
printf(" %c",BT->Data);
return;
}
if(BT->Left != NULL){
return PreorderPrintLeaves(BT->Left);
}
if(BT->Right != NULL){
return PreorderPrintLeaves(BT->Right);
}
}
BinTree Insert( BinTree BST, ElementType X ){
if (!BST) { //当递归到正确位置时创造结点
BST = (BinTree) malloc(sizeof(struct TNode));
BST->Right = NULL;
BST->Left = NULL;
BST->Data = X;
}
if(BST->Data > X) BST->Left = Insert(BST->Left,X); //根据二叉搜索树的特性,小了往左,大了往右,一直到叶节点为止
if(BST->Data < X) BST->Right = Insert(BST->Right,X);
return BST;
}
/**
* 二叉搜索树的删除有三种情况:
* 1.被删除节点为叶子结点,此时什么都不用做,直接删除
* 2.被删除节点只有左结点或右结点,用子结点代替即可
* 3.被删除节点有两个孩子,那么我们使用它的后继(或前驱)结点替换它,并且删除前驱结点
* @param BST
* @param X
* @return
*/
BinTree Delete( BinTree BST, ElementType X ){
if(!BST){
printf("Not Found\n");
return BST;
}
if(BST->Data < X) BST->Right = Delete(BST->Right,X);
if(BST->Data > X) BST->Left = Delete(BST->Left,X);
if(BST->Data == X){
if(BST->Left == NULL || BST->Right == NULL){
BST = BST->Left == NULL ? BST->Right : BST->Left;
} else {
Position temp = FindMin(BST->Right);
BST->Data = temp->Data; //注意只是把内容替换,务必不要整个替换节点
BST->Right = Delete(BST->Right,BST->Data);//删除结点
}
}
return BST;
}
Position Find( BinTree BST, ElementType X ){
if(!BST) return NULL;
if(BST->Data == X) return BST;
else if(BST->Data > X) return Find(BST->Left,X);
else return Find(BST->Right,X);
}
Position FindMin( BinTree BST ){
if(!BST) return NULL;
if (BST->Left) {
return FindMin(BST->Left);
}
return BST;
}
Position FindMax( BinTree BST ){
if(!BST) return NULL;
if (BST->Right) {
return FindMax(BST->Right);
}
return BST;
}
Position Find(BinTree BST, ElementType X){
while (BST){
if (X > BST->Data) BST = BST->Right;
else if (X < BST->Data) BST = BST->Left;//此处一定要加else,下同
else if(X==BST->Data) return BST;
}
return NULL;
}
Position FindMin( BinTree BST ){
if(!BST) return NULL;
while(BST->Left) BST = BST->Left;
return BST;
}
Position FindMax( BinTree BST ){
if(!BST) return NULL;
while(BST->Right) BST = BST->Right;
return BST;
}
BinTree Insert( BinTree BST, ElementType X ){
if(!BST){
BST = (BinTree)malloc(sizeof(struct TNode));
BST->Data = X;
BST->Left = NULL;
BST->Right = NULL;
}
if(X < BST->Data) BST->Left = Insert(BST->Left, X);
if(X > BST->Data) BST->Right = Insert(BST->Right, X);
return BST;
}
BinTree Delete( BinTree BST, ElementType X ){
Position temp;
if(!BST){
printf("Not Found\n");
return BST;
}
if(X < BST->Data) BST->Left = Delete(BST->Left, X);
if(X > BST->Data) BST->Right = Delete(BST->Right, X);
if(X==BST->Data){
if(BST->Left&&BST->Right){
temp = FindMin(BST->Right);
BST->Data = temp->Data;
BST->Right = Delete(BST->Right, BST->Data);
}
else{
if(BST->Left) BST = BST->Left;
else BST = BST->Right;
}
}
return BST;
}
#include
/**
*Created by salmon on 2021-9-25 22:30.
**/
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
int degree0Count = 0;
int degree1Count = 0;
int degree2Count = 0;
void nodeCountOfVariousDegree( BinTree BT ,int °ree0Count, int °ree1Count, int °ree2Count ){
if(!BT) return;
if(BT->Left == NULL && BT->Right == NULL){
degree0Count++;
}else if((BT->Left == NULL && BT->Right != NULL) || (BT->Right == NULL && BT->Left != NULL)){
degree1Count++;
}else if(BT->Left != NULL && BT->Right != NULL){
degree2Count++;
}
if(BT->Left != NULL){
nodeCountOfVariousDegree(BT->Left,degree0Count,degree1Count,degree2Count);
}
if(BT->Right != NULL){
nodeCountOfVariousDegree(BT->Right,degree0Count,degree1Count,degree2Count);
}
}
int main(){
BinTree binTree = (BinTree)malloc(sizeof(struct TNode));
// binTree->Left = NULL;
binTree->Left = (BinTree)malloc(sizeof(struct TNode));
binTree->Left->Left = NULL;
binTree->Left->Right = NULL;
// binTree->Right = (BinTree)malloc(sizeof(struct TNode));
// binTree->Right->Left = NULL;
// binTree->Right->Right = NULL;
binTree->Right == NULL;
nodeCountOfVariousDegree(binTree,degree0Count,degree1Count,degree2Count);
printf("%d\n",degree0Count);
printf("%d\n",degree1Count);
printf("%d\n",degree2Count);
}
/**
*Created by salmon on 2021-9-29 22:50.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
void SpecialLevelTraversebt(BinTree BT){ //即与正常的层次遍历算法的输出反着来,多添加一个栈来实现
if(BT == NULL) return;
Queue Q = initQueue();
Stack S = initStack();
EnQueue(BT);
while ( !isEmpty(Q) ) {
BinTree temp = DeQueue();
Push(temp);
if(temp->Left){
EnQueue(temp->Left);
}
if(temp->Right){
EnQueue(temp->Right);
}
}
while ( !isEmpty(S) ){
BinTree res = Pop(S);
visit(res->Data);
}
}
/**
*Created by salmon on 2021-9-29 23:12.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
/**
* 具体思路为,进行普通的层序遍历,唯一不同的是即使当前结点为叶子结点,我们依旧把左右孩子入队列,
* 当遍历到空节点时,说明已经遍历到第一个叶子结点的孩子结点,那么从这里开始队列中的剩余结点均为空结点,
* 所以如果剩余结点有不为空的结点,那么就不是完全二叉树
* @param BT
* @return
*/
bool isCompleteTree(BinTree BT){
if(!BT) return true; //如果树为空,是完全二叉树
Queue Q = InitQueue();
EnQueue(BT);
while ( !isEmpty(Q) ){
BinTree BT = DeQueue(Q);
if(BT){
EnQueue(BT->Left);
EnQueue(BT->Right);
} else {
while ( !isEmpty(Q) ){
BinTree BT = DeQueue(Q);
if(BT) return false;
}
return true;
}
}
}
/**
*Created by salmon on 2021-9-29 23:30.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
/**
* 要自底向上的交换,递归方法类似于后序遍历
* @param BT
*/
void swap(BinTree BT){
if(BT){
swap(BT->Left);
swap(BT->Right);
BinTree temp = BT->Left;
BT->Left = BT->Right;
BT->Right = temp;
}
}
/**
*Created by salmon on 2021-10-1 00:23.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
void delete(BinTree BT){
if(BT){ //删除该树时应从底部开始删除,类似于后序遍历
delete(BT->Left);
delete(BT->Right);
free(BT);
}
}
/**
* 比较方便的思路是层次遍历整棵树,如果找到X则删除它以及以它为根节点的子树
* @param BT
* @param X
*/
void searchAndDelete(BinTree BT,ElementType X){
if(BT == NULL) return;
if(BT->Data == X) return delete(BT);
Queue Q = initQueue();
EnQueue(BT);
while ( !isEmpty(Q) ){
BinTree temp = DeQueue(Q);
if(temp->Left){
if(temp->Left->Data == X){ //查找时,我们让指针停留在父节点,用父节点的左右孩子来进行对比,这样有利于删除操作。
delete(temp->Left);
temp->Left = NULL;
} else {
EnQueue(temp->Left);
}
}
if(temp->Right){
if(temp->Right->Data == X){
delete(temp->Right);
temp->Right = NULL;
} else {
EnQueue(temp->Right);
}
}
}
}
/**
*Created by salmon on 2021-10-3 23:48.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
void SearchAncestorOfX(BiTree T, ElementType X){
InitStack(S);
BiTree p = T; //p为遍历指针
BiTree record = NULL; //record为辅组指针,指向最近访问过的结点。
while(p || !StackIsEmpty(S)) {
if(p) {
push(S, p);
p = p->lchild; //左孩子不空,一直向左走
} else { //向右
GetTop(S,p); //读栈顶结点(非出栈)
if(p->data == X) {//如果栈顶结点的值等于x
pop(S,P);//先把当前结点pop了,因为只需要打印所有祖先
while(!StackIsEmpty(S)) {//将剩下的祖先依次打印
pop(S, p);
visit(p); //访问该结点
}
return 0; //执行完毕返回
}
if(p->rchild && p->rchild != record) {//若右子树存在,且未被访问过
p = p->rchild; //转向右
push(S, p);
p = p->lchild; //再走到最左
} else {//否则,弹出结点
pop(S, p);
record = p; //记录最近访问过的结点
p = NULL; //结点访问完毕后,重置p指针,不然该结点又会重新入栈
}
}
}
}
此题有些异议,一些题目中的宽度是树每层结点个数的最大值,另一些题目中先将一颗树转换为完全二叉树(一层中相隔的结点之间有空位的话补上结点),宽度指转换后的树每层结点个数的最大值
/**
*Created by salmon on 2021-10-5 00:33.
**/
#include
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
int GetWidth( BinTree BT ){ //在脑中想象一颗只有2层的满二叉树可以更好地理解
if (BT == NULL) return 0;
Queque Q = initQueue();//初始化队列
EnQueque(BT);
int front = 0, rear = 1,last = rear;
int width = 1;
while (front < rear) {
BinTree curr = DeQueue();
if ( curr -> Left != NULL ) {
EnQueue(curr -> Left);
rear++;
}
if( curr -> Right != NULL ) {
EnQueue(curr -> Right);
rear++;
}
front++;
if(front == last){
width = width < (rear - front) ? (rear - front) : width;
last = rear;
}
}
return width;
}
/**
*Created by salmon on 2021-10-10 23:29.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree firstChild;
BinTree nextsibling;
};
int leaves(BinTree BT){
if(BT == NULL){
return 0;
} else {
if(BT->firstChild == NULL){
return 1 + leaves(BT->nextsibling);
} else {
return leaves(BT->nextsibling) + leaves(BT->firstChild);
}
}
}
/**
*Created by salmon on 2021-10-10 23:40.
**/
#include
#include
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree firstChild;
BinTree nextsibling;
};
int Height(BinTree BT){
if(BT == NULL){
return 0;
} else {
int childHigh = Height(BT->firstChild);
int broChildHigh = Height(BT->nextsibling);
return childHigh + 1 > broChildHigh ? childHigh + 1 : broChildHigh;
}
}
/**
*Created by salmon on 2021-10-8 23:41.
**/
#include
/**
* 希尔排序大多数流行的是三种写法,这里取第二种:其它几种可参考链接:https://wenku.baidu.com/view/aa8a4fd2b0717fd5360cdced.html
* 希尔排序即将原数组s[]分割成多个以增量d为标准的数组,再对其进行直接插入排序 默认为非递减排序
* 本程序使用第二种写法,也是大多数教科书上的写法,这种写法与我们所学的分组后进行直接插入排序不同
* 此种是从数组第一个元素开始依次向后扫描,每次比较的都是相隔d个的元素,显然也是符合希尔排序逻辑的实现方式,只不过进行了化整体为部分的操作
* @param s
* @param n
*/
void shellSort( int s[], int n ) { //n为有效数组长度,实际数组长度为n+1,s[0]作为数据保存单元
int i,j,d; //d为增量,j为已有序数组的最后一个元素下标
for (d = n / 2; d >= 1; d = d / 2) {
for( i = d + 1; i <= n; i++ ) { //数组下标从分好组的第二个元素开始进行直接插入排序,第一个元素默认形成了一个有序数列
s[0] = s[i]; //保存当前参照元素
for ( j = i - d; j > 0 && s[0] < s[j]; j = j - d ) {
//自后向前扫描已有序数组,如果已有序数组中有大于当前参照元素的,就将该元素后移
s[j + d] = s[j];
//继续向前扫描,j向前移d个位置,当j小于或等于0时结束
}
s[j + d] = s[0]; //找到了应该插入的位置的前一个位置
}
}
}
int main()
{
int a[11],i; /*定义数组及变量为基本整型*/
printf("请输入 10 个数据:\n");
for(i=1;i<=10;i++)
scanf("%d",&a[i]); /*从键盘中输入10个数据*/
shellSort(a, 10); /* 调用 shsort()函数*/
printf("排序后的顺序是:\n");
for(i=1;i<=10;i++){
printf("%5d",a[i]); /*输出排序后的数组*/
}
return 0;
}
/**
*Created by salmon on 2021-10-12 23:15.
**/
#include
void QuickSort(int *, int, int); /*现在只需要定义一个函数, 不用交换还省了一个函数, 减少了代码量*/
int main()
{
int i; //循环变量
int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
QuickSort(a, 0, 20); /*引用起来很简单, 0为第一个元素的下标, 20为最后一个元素的下标*/
printf("最终排序结果为:\n");
for (i=0; i<21; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
void QuickSort (int *a, int low, int high) {
int i = low;
int j = high;
int key = a[low]; //把比较值保存起来,有的书上是使用a[0]保存起来,以你报考学校参考书为准
if (low >= high) return;
while (low < high) {
while (low < high && key <= a[high]) {
high--;
}
if (low != high) {
a[low] = a[high];
low++;
}
while (low < high && key >= a[low]) {
low++;
}
if (low != high) {
a[high] = a[low];
high--;
}
}
//此时low == high ,已经找到key的最终位置
a[low] = key; //此时以key为分界线将序列分成左右两部分
QuickSort(a, i, low - 1); //用同样的方式对分出来的左边的部分进行同上的做法
QuickSort(a, low + 1, j); //用同样的方式对分出来的右边的部分进行同上的做法
}
/**
*Created by salmon on 2021-10-13 23:42.
**/
#include
void BubbleSort( int num[], int length ){ //num为传入的数组,length为数组长度,这里用从后往前冒泡
for (int i = 0; i < length; i++) {
int flag = 0;
for (int j = length - 1; j > i; j--) {
if(num[j] < num[j - 1]){
int temp = num[j - 1];
num[j - 1] = num[j];
num[j] = temp;
flag++;
}
}
if(flag == 0){
break;
}
}
}
int main()
{
int i;
int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
BubbleSort(a, 21);
printf("最终排序结果为:\n");
for (i=0; i < 21; ++i){
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
/**
*Created by salmon on 2021-10-23 00:40.
**/
#include
#define Maxsize 100
/**
* 将num[low....mid]与num[mid + 1 ...high]合并成一个有序数组,升序
* @param num
* @param low
* @param mid
* @param high
*/
void merge(int num[],int low,int mid,int high){
int assist[Maxsize]; //定义一个辅助数组
int i,j,cur;
for (cur = low; cur <= high ; ++cur) {
assist[cur] = num[cur]; //将A中数组复制到辅助数组中
}
for (i = low,j = mid + 1,cur = i; i <= mid && j <= high; cur++) { //比较两个数组,将较小的元素移动到左边
if(assist[i] <= assist[j]){
num[cur] = assist[i];
i++;
} else {
num[cur] = assist[j];
j++;
}
}
//以下是当两个中有某一个数组率先扫描完成时所需要做的操作,即将剩余数按顺序放入到原数组中
while (i <= mid) {
num[cur] = assist[i];
cur++;
i++;
}
while (j <= high) {
num[cur] = assist[j];
cur++;
j++;
}
}
void mergeSort(int num[],int low, int high){
if(low < high){
int mid = (low + high) / 2;
mergeSort(num,low,mid);
mergeSort(num,mid + 1,high);
merge(num,low,mid,high);
}
}
/**
*Created by salmon on 2021-10-15 23:58.
**/
#include
void SelectSort(int a[],int length){ //选择排序
int mixIndex,temp;
int i,j;
for(i = 0; i < length - 1; i++){ //每次循环数组,找出最小的元素,放在前面,前面的即为排序好的
mixIndex = i; //假设最小元素的下标
for(j = i + 1; j < length; j++){ //将上面假设的最小元素与数组比较,交换出最小的元素的下标
if(a[j] < a[mixIndex])
mixIndex = j;
}
if(i != mixIndex) {
temp = a[i];
a[i] = a[mixIndex];
a[mixIndex] = temp;
}
}
}
int main()
{
int i;
int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
SelectSort(a, 21);
printf("最终排序结果为:\n");
for (i=0; i < 21; ++i){
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
/**
*Created by salmon on 2021-10-20 23:54.
**/
#include
//二分查找过程,查找key应插入的位置
int binarySearch(int num[], int key, int low, int high) {
int mid = -1;
//循环直到low>high,此时low即为要插入的位置
while (low <= high) {
mid = (low + high) / 2;
if (key <= num[mid])
high = mid - 1;
else
low = mid + 1;
}
return low;
}
//使用二分查找改进插入排序,使之最坏情况下时间复杂度为Θ(nlgn)
void binInsertionSort(int num[], int n) {
for (int i = 1; i < n; i++) {
int key = num[i];
int index = binarySearch(num, key, 0, i);
if (index != i) {
//如果需要移动,则往后移动一个位置,把位置腾出来
for (int j = i - 1; j >= index; j--) {
num[j + 1] = num[j];
}
//把A[i]放到正确的位置
num[index] = key;
}
}
}
int main()
{
int i;
int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
binInsertionSort(a, 21);
printf("最终排序结果为:\n");
for (i=0; i < 21; ++i){
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
/**
*Created by salmon on 2021-10-24 23:24.
**/
#include
#include
//带头结点链表,将小于第一个元素的结点放在其前面,大于放在后面
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType data;
PtrToNode next;
};
typedef PtrToNode List;
void change( List L ){
if(L -> next == NULL) return;
List p, end, first, pre;//end是末尾指针
first = L -> next; //first指向L单链表的第一个元素
p = first -> next; //p指向遍历当前结点
pre = first; //pre指向p的前一个结点
while ( p ) { //遍历单链表
end = p->next;
if(p -> data < first -> data){ //遇到比第一个元素小的则头插法插入
pre->next = end;
p->next = L->next;
L->next = p;
p = end;
} else { //其他则继续往后遍历
p = p->next;
pre = pre->next;
}
}
}
/**
*Created by salmon on 2021-10-24 23:58.
**/
Definition for a binary tree node.
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};
bool traversal(struct TreeNode* left,struct TreeNode *right){
if(left == NULL && right == NULL){
return true;
}
if(left == NULL || right == NULL) {
return false;
}
if(left->val != right-> val) {
return false;
}
return traversal(left->left, right->right) && traversal(left->right, right->left);
}
bool isSymmetric(struct TreeNode* root){
if (root == NULL) {
return true;
}
return traversal(root->left, root->right);
}