Data_Structure/作業/unit7/Threaded Binary Tree_stack.cpp
2025-01-20 21:30:53 +08:00

417 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*Notes: 輸入可為
w={"Mary":10, "Tom":3, "Charlie":5, "Bob":6, "Dickens":20, 4:9, "z":0, "Za":12, "aZ":8}
w={10:10, 20:3, 5:5, 17:6, 23:20, 18:9, 3:0, 9:12}
w={10:10, 5:5, 9:6, 3:20, 7:9}
w={"A":10, "B":3, "Charlie":5, "Bob":6, "Dickens":20}
w={"D":10, "C":3, "B":5, "A":6}
del w["A"]
del w["Dickens"]
del w["Mary"]
del w["aZ"]
del w
w["Mary"]=1
w["Tom"]+=2
w[4]?
w?
*/
#include <stdio.h> /* for sscanf(), printf() */
#include <stdlib.h>
#include <string.h> /* for strstr(), strtok(), strtok_r() */
#include <conio.h>
#define MAX_STACK 100 // 定義堆疊大小
/* 定義dict結構 */
typedef struct dict { /* 引線二元搜尋樹節點之資料結構,實作字典 */
char key[20]; /* 紀錄該節點的「鍵」(key)內容 */
int value; /* 紀錄「鍵」對應之「值」(value)內容 */
struct dict *llink; /* 指向左子樹根或引線用途 */
struct dict *rlink; /* 指向右子樹根或引線用途 */
int lbit; /* 指示 llink 是否為正常指標 */
int rbit; /* 指示 rlink 是否為正常指標 */
} dict;
// 定義堆疊結構
typedef struct {
dict* data[MAX_STACK];
int top;
} Stack;
void show(void); /* 輸出函數 */
void insert(char [], int); /* 將資料加入二元搜尋樹 */
void removing(char []); /* 將資料從二元搜尋樹中移除 */
void inorder(struct dict *); /* 資料以中序法輸出 */
void free_all_nodes(struct dict *node);
void find_newroot(void); /* 搜尋新的樹跟節點 */
dict *search_p(struct dict *node);
dict *search(char []); /* 搜尋節點 */
dict *root = NULL, *ptr, *prev ,*head = NULL ;
// 堆疊操作函數
void initStack(Stack *s) {
s->top = -1;
}
int isEmpty(Stack *s) {
return s->top == -1;
}
int isFull(Stack *s) {
return s->top == MAX_STACK - 1;
}
void push(Stack *s, dict* node) {
if (!isFull(s)) {
s->data[++(s->top)] = node;
}
}
dict* pop(Stack *s) {
if (!isEmpty(s)) {
return s->data[(s->top)--];
}
return NULL;
}
void inorder(struct dict *root) {
if (root == NULL) {
return;
}
Stack stack;
initStack(&stack);
dict *current = root;
while (current != NULL || !isEmpty(&stack)) {
// 將所有左子節點推入堆疊
while (current != NULL) {
push(&stack, current);
current = current->llink;
}
// 從堆疊中取出節點並處理
current = pop(&stack);
if (current != NULL) {
printf("%s%d\n", current->key, current->value);
// 移動到右子節點
current = current->rlink;
}
}
}
// 非遞迴方式釋放所有節點
void free_all_nodes(struct dict *root) {
if (root == NULL) {
return;
}
Stack stack;
initStack(&stack);
dict *current = root;
dict *last_processed = NULL;
while (current != NULL || !isEmpty(&stack)) {
if (current != NULL) {
push(&stack, current);
current = current->llink;
} else {
dict *peek = stack.data[stack.top];
// 如果右子節點存在且尚未處理
if (peek->rlink != NULL && last_processed != peek->rlink) {
current = peek->rlink;
} else {
peek = pop(&stack);
printf("刪除'w[%s]=%d'節點\n", peek->key, peek->value);
last_processed = peek;
free(peek);
current = NULL;
}
}
}
}
void show(void) {
if (root == NULL) {
puts("二元搜尋樹是空的!");
return;
}
printf("字典變數內部儲存的元素(keyvalue)如下\n");
inorder(root);
}
int main(){
head = (dict *)malloc(sizeof(dict));
if (head == NULL) {
printf("記憶體分配失敗!\n");
return 1;
}
head->lbit = head->rbit = 1;
head->rlink = head;
head->llink = root;
char *token, key[12], line[128];
const char *s = " ={},"; /* 分隔符記的字元 */
int value;
char *rest ,option;
printf("輸入存取字典的陳述,逕按<Enter>結束程式\n");
while (1) {
printf("\n指令 => ");
fgets(line,128,stdin); /* 使用gets()讀取也可以但因gets()未設讀入字元數的限制,可能導致儲存輸入字元的陣列空間爆掉 */
if (line[0]=='\n') break; /* 輸入空字串則跳離此迴圈 */
if (strstr(line,"{")) { /* line含有"{" */
sscanf(line,"w = {%[^}]}",line);
rest = line;
while (token = strtok_r(rest,s,&rest)) { /* strtok_r()的用法可參見 http://bit.ly/3VcvbbZ */
/* printf("%s\n",token); */
if (strstr(token,":")) {/* token含有":" */
sscanf(token,"%[^:]:%d",key,&value);
insert(key,value);
// printf("Token #%d: 鍵=%s; 值=%d\n",++i,key,value);
}
}
}else if (strstr(line,"del")) {
if(sscanf(line,"del w[%[^]]]",key)){
if(strcmp(key,root->key)==0){
// printf("刪除的元素w[%s]為root節點\n",key);
find_newroot();
// printf("新的root節點為w[%s]\n",root->key);
}else removing(key);
}else{
printf("無法判讀將刪除哪一個元素,將刪除整個字典? (y/n) => ");
scanf("%c",&option);
fflush(stdin);
if (option == 'y' || option == 'Y') {
free_all_nodes(root);
root = NULL;
}else{
printf("取消刪除所有字典\n");
}
}
}else if (strstr(line,"+=")) { /* line含有"+=" */
sscanf(line,"w[%[^]]] +=%d",key,&value);
dict *modify_node;
if((modify_node = search(key)) == NULL){ /* 找不到資料則顯示錯誤 */
printf("錯誤! %s 不在此二元搜尋樹中!\n", key);
}else{
modify_node->value += value;
printf("新設w[%s]=%d\n",key,modify_node->value);
}
}else if (strstr(line,"=")) { /* line含有"=" */
sscanf(line,"w[%[^]]] = %d",key,&value);
dict *add_node;
if (root == NULL){
insert(key,value);
printf("新設w[%s]=%d\n",key,root->value);
}else{
if((add_node = search(key)) == NULL){ /* 找不到資料則新增資料 */
insert(key,value);
printf("%s 不在此二元搜尋樹中!\n", key);
printf("新設w[%s]=%d\n",key,value);
}else{
add_node->value = value;
printf("新設w[%s]=%d\n",key,add_node->value);
}
}
}else if (sscanf(line,"w[%[^]]]?",key)==1){
dict *read_node;
if((read_node = search(key)) == NULL){ /* 找不到資料則新增資料 */
printf("錯誤! %s 不在此二元搜尋樹中!\n", key);
}else{
printf("字典元素w[%s]=%d\n",key,read_node->value);
}
}else if (strstr(line,"?")) show();
else printf("語法無法辨認sorry!\n");
}
printf("\n程式結束刪除所有節點bye ~\n");
free_all_nodes(root);
free(head);
return 0;
}
/* 處理二元搜尋樹,將新增資料加入至二元搜尋樹中 */
void insert(char key[], int value){
struct dict *node, *prev;
/* 資料已存在則顯示錯誤 */
if (search(key) != NULL) {
printf("%s 已存在!\n", key);
return;
}
ptr = (struct dict *) malloc(sizeof(struct dict));
strcpy(ptr->key, key);
ptr->value = value;
ptr->llink = ptr->rlink = NULL;
ptr->lbit = ptr->rbit = 0;
if (root == NULL){/* 當根節點為NULL的狀況 */
root = ptr;
ptr->lbit = ptr->rbit = 1;
}else{ /* 當根節點不為NULL的狀況 */
node = root;
while (node != NULL) { /* 搜尋資料插入點 */
prev = node;
if(strcmp(ptr->key, node->key) < 0)
node = node->llink;
else
node = node->rlink;
}
if (strcmp(ptr->key, prev->key) < 0){
prev->llink = ptr;
prev->lbit = 1;
}else{
prev->rlink = ptr;
prev->rbit = 1;
}
}
}
/* 將資料從二元搜尋樹中移除 */
void removing(char key[]){
dict *del_node = search(key);
if (del_node == NULL) {
printf("%s 不在此二元搜尋樹中!\n", key);
return;
}
dict *parent = search_p(del_node);
// 處理沒有子節點的情況
if (del_node->llink == NULL && del_node->rlink == NULL) {
if (parent == NULL) { // 刪除的是根節點
root = NULL;
} else if (parent->llink == del_node) {
parent->llink = NULL;
} else {
parent->rlink = NULL;
}
}else if (del_node->llink == NULL || del_node->rlink == NULL) { // 處理一邊有子節點的情況
dict *child = (del_node->llink != NULL) ? del_node->llink : del_node->rlink;
if (parent == NULL) { //刪除的是根節點
root = child;
} else if (parent->llink == del_node) {
parent->llink = child;
} else {
parent->rlink = child;
}
}else{ //處理兩邊有子節點的情況
if(del_node == parent->rlink){
parent->rlink = del_node->llink;
if(del_node->llink->rlink != NULL){ //若刪除的節點的子節點還有右節點的情況
dict *child = del_node->llink->rlink;
printf("%s\n",child->key);
while(child->rlink!= NULL){ //找右節點直到最底
child = child->rlink;
printf("%s\n",child->key);
}
child->rlink = del_node->rlink;
}else parent->rlink->rlink = del_node->rlink; //沒有則直接替換
}else{
parent->llink = del_node->llink;
if(del_node->rlink->llink != NULL){ //若刪除的節點的子節點還有左節點的情況
dict *child = del_node->rlink->llink;
printf("%s\n",child->key);
while(child->llink!= NULL){ //找左節點直到最底
child = child->llink;
printf("%s\n",child->key);
}
child->llink = del_node->llink;
}else parent->llink->rlink = del_node->rlink; //沒有則直接替換
}
}
free(del_node); /* 釋放記憶體 */
printf("刪除w[%s]元素\n",key);
}
void find_newroot(){ /* 搜尋新的樹跟節點 左連結最大值*/
struct dict *newroot_node ,*prev;
if(root->llink!=NULL){ //找左連結的最大值
newroot_node = root->llink;
while(newroot_node->rlink!=NULL){ //找根的替代節點
prev = newroot_node;
newroot_node = newroot_node->rlink;
}
if(newroot_node->llink!=NULL){ //若新的根節點有左節點
prev->rlink = newroot_node->llink;
}else prev->rlink = NULL;
if(newroot_node != root->llink ){ //若新的根節點不等於原本根的左節點
newroot_node->llink = root->llink;
newroot_node->rlink = root->rlink;
}else{ //若新的根節點等於原本根的左節點
newroot_node->rlink = root->rlink;
}
printf("刪除w[%s]元素\n",root->key);
free(root);
root = newroot_node;
}else if(root->rlink!=NULL){ //找右連結的最小值
newroot_node = root->rlink;
while(newroot_node->llink!=NULL){ //找根的替代節點
prev = newroot_node;
newroot_node = newroot_node->llink;
}
if(newroot_node->rlink!=NULL){ //若新的根節點有右節點
prev->llink = newroot_node->rlink;
}else prev->llink = NULL;
if(newroot_node != root->rlink ){ //若新的根節點不等於原本根的右節點
newroot_node->llink = root->llink;
newroot_node->rlink = root->rlink;
}else{ //若新的根節點等於原本根的右節點
newroot_node->llink = root->llink;
}
printf("刪除w[%s]元素\n",root->key);
free(root);
root = newroot_node;
}
}
/* 搜尋target所在節點 */
struct dict *search(char target[]){
struct dict *node;
node = root;
while(node != NULL)
{
if (strcmp(target, node->key) == 0)
return node;
else
/* target小於目前節點往左搜尋 */
if (strcmp(target, node->key) < 0)
node = node->llink;
else /* target大於目前節點往右搜尋 */
node = node->rlink;
}
return node;
}
/* 搜尋node的父節點 */
struct dict *search_p(struct dict *node){
struct dict *parent;
parent = root;
while (parent != NULL) {
if (strcmp(node->key, parent->key) < 0) {
if (strcmp(node->key, parent->llink->key) == 0)
return parent;
else
parent = parent->llink;
}
else {
if (strcmp(node->key, parent->rlink->key) == 0)
return parent;
else
parent = parent->rlink;
}
}
return NULL;
}