這作業我搞了整個週末才寫出個雛形,說寫了超過24小時一點也不為過。
由於第一次寫這麼大結構的程式,故程式碼有些冗長且重複使用性極低。僅供參考。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct node { //宣告singly linked list結構
int data;
struct node *next;
};
struct nodeDLL { //宣告doubly linked list結構
int data;
struct nodeDLL *prev, *next;
};
struct node *first = NULL; //宣告指向首端的結構指標
struct nodeDLL *firstDLL = NULL, *tailDLL = NULL; //宣告指向首端及尾端的結構指標
void build_a_list(struct node **first, int n); //宣告singly linked list函數群
void print_list(struct node *first);
void clean_list(struct node *first);
void insert_to_list(struct node **first);
void search_list();
void delete_from_list();
void count_list();
void reverse_list();
void merge_list(int n);
void split_list();
void build_a_DLL(struct nodeDLL **firstDLL, struct nodeDLL **tailDLL, int n); //宣告doubly linked list函數群
void prePrint_DLL(struct nodeDLL *firstDLL);
void postPrint_DLL(struct nodeDLL *firstDLL);
void clean_DLL(struct nodeDLL *firstDLL);
void insert_to_DLL(struct nodeDLL **firstDLL, struct nodeDLL **tailDLL);
void search_DLL();
void delete_from_DLL();
void count_DLL();
void reverse_DLL();
void merge_DLL(int n);
void split_DLL();
int main(void)
{
int DS, n; //DS讀入資料結構型態
char F; //F讀入執行函數類型
printf("Please select the data structure or exit: ");
scanf("%d", &DS);
srand(time(NULL));
n = rand() % 10 + 3; //先創造一隨機長度的linked list
if (DS == 1) {
printf("Please enter %d numbers to create a initial list: ", n);
build_a_list(&first, n);
print_list(first);
}
else if (DS == 2) {
printf("Please enter %d numbers to create a initial list: ", n);
build_a_DLL(&firstDLL, &tailDLL, n);
prePrint_DLL(firstDLL);
}
else
return 0;
while (1) {
getchar(); //吸收多input的Enter
printf("Please select the function: ");
scanf("%c", &F);
if (DS == 1) { //若選擇singly linked list則執行此選單
switch (F) {
case 'a':
printf("Enter the number you want to insert: ");
insert_to_list(&first);
break;
case 'b':
delete_from_list();
break;
case 'c':
search_list();
break;
case 'd':
count_list();
break;
case 'e':
reverse_list();
break;
case 'f':
merge_list(n);
break;
case 'g':
split_list();
break;
case 'h':
print_list(first);
break;
case 'x':
clean_list(first);
return 0;
}
}
else { //若選擇doubly linked list則執行此選單
switch (F) {
case 'a':
printf("Enter the number you want to insert: ");
insert_to_DLL(&firstDLL, &tailDLL);
break;
case 'b':
delete_from_DLL();
break;
case 'c':
search_DLL();
break;
case 'd':
count_DLL();
break;
case 'e':
reverse_DLL();
break;
case 'f':
merge_DLL(n);
break;
case 'g':
split_DLL();
break;
case 'h':
prePrint_DLL(firstDLL);
break;
case 'i':
postPrint_DLL(tailDLL);
break;
case 'x':
clean_DLL(firstDLL);
return 0;
}
}
}
}
void build_a_list(struct node **first, int n) //創造一隨機長度的linked list
{
int i;
struct node *new_node, *prev = NULL, *cur;
new_node = malloc(sizeof(struct node)); //創造第一個節點空間
if (new_node == NULL) { //若創造失敗則印出錯誤
printf("Error: malloc failed.\n");
return;
}
new_node->next = *first; //first指向第一個節點
*first = new_node;
for (i = 0; i < n; i++) {
cur = *first;
scanf("%d", &new_node->data); //讀入數字到節點
while (cur->data < new_node->data && cur->next != NULL) { //由小到大排列節點
prev = cur;
cur = cur->next;
}
if (cur->data < new_node->data && cur->next == NULL) { //若原始list內沒有節點的數字比欲插入之節點大,則節點放到尾端
cur->next = new_node;
new_node->next = NULL;
}
else if (prev == NULL) { //若首端節點數字即比欲插入節點大,則將first指向欲插入之節點,並將節點與原list連結
if (new_node->next == NULL) //若list內無任何節點,則不需做連結
;
else {
*first = new_node;
}
}
else { //若為其他狀況則將前一個節點和欲插入之節點連結,欲插入之節點和後一個節點連結
prev->next = new_node;
new_node->next = cur;
}
new_node = malloc(sizeof(struct node)); //再創一個新節點空間
if (new_node == NULL) { //若創造失敗則印出錯誤
printf("Error: malloc failed.\n");
return;
}
if (i == n - 1) //若為最後一次跑for loop,則釋放剛創的節點空間
free(new_node);
}
}
void print_list(struct node *first) //印出linked list
{
if (first == NULL) { //若無list,則印出訊息
printf("There is no list.\n");
return;
}
struct node *cur;
for (cur = first; cur != NULL; cur = cur->next) //從第一個節點開始循序印出數字
printf("%d ", cur->data);
printf("\n");
}
void clean_list(struct node *first) //清除linked list
{
struct node *prev, *cur;
for (cur = first; cur != NULL;) {
prev = cur;
cur = cur->next;
first = cur;
free(prev);
}
first = NULL;
}
void insert_to_list(struct node **first) //插入一個新節點
{
struct node *new_node, *prev = NULL, *cur;
new_node = malloc(sizeof(struct node)); //創造新節點空間
if (new_node == NULL) { //若創造失敗則印出訊息
printf("Error: malloc failed.\n");
return;
}
scanf("%d", &new_node->data); //讀入數字
if (*first == NULL) { //若無list可插入新節點則印出訊息
printf("There is no list to insert a new node.\n");
free(new_node);
return;
}
for (cur = *first; cur->data < new_node->data && cur->next != NULL;) { //確定新節點位置
prev = cur;
cur = cur->next;
}
if (prev == NULL) { //若為第一個則first指向新節點,並將新節點與原list連結
new_node->next = *first;
*first = new_node;
}
else {
if (cur->next == NULL) { //若為最後一個則原list尾端節點與之連結
cur->next = new_node;
new_node->next = NULL;
}
else { //其他狀況則前一個和後一個與之連結
prev->next = new_node;
new_node->next = cur;
}
}
}
void delete_from_list() //從list中刪除一個節點
{
int n;
struct node *cur, *prev = NULL;
if (first == NULL) { //若無list則印出訊息
printf("Nothing to delete.\n");
return;
}
printf("Enter the number you want to delete: "); //印出要求
scanf("%d", &n); //讀入數字
for (cur = first; cur != NULL && cur->data != n; prev = cur, cur = cur->next) //定位
;
if (cur == NULL) { //若找不到欲刪除之節點則印出訊息
printf("The number doesn't exist in the list.\n");
return;
}
else if (prev == NULL) //若為首端節點則將first指向下一個節點
first = cur->next;
else //其他狀況則前一個與後一個連結
prev->next = cur->next;
free(cur); //釋放節點空間
printf("The node has been deleted.\n"); //印出訊息
}
void search_list() //搜尋節點
{
int n, num_node = 1;
struct node *cur;
cur = first;
printf("Enter the number you want to search: "); //印出要求
scanf("%d", &n); //讀入數字
for (; cur != NULL; cur = cur->next, num_node++) //搜尋是否存在
if (cur->data == n) {
printf("The number is in no.%d list.\n", num_node); //存在則印出訊息
return;
}
printf("The number doesn't exist in the list.\n"); //不存在則印出訊息
}
void count_list() //計算節點數
{
int num_nodes = 0;
struct node *cur;
for (cur = first; cur != NULL; cur = cur->next) //計算節點數後印出結果
num_nodes++;
printf("There are %d nodes in the list.\n", num_nodes);
}
void reverse_list() //反轉list
{
struct node *prev, *cur;
cur = first;
first = NULL;
while (cur != NULL) { //反轉各節點間的連結並改變first指向
prev = cur;
cur = cur->next;
prev->next = first;
first = prev;
}
printf("The list has been reversed.\n"); //印出訊息
}
void merge_list(int n) //合併兩條linked list
{
int i;
struct node *head = NULL;
srand(time(NULL));
n = rand() % 10 + 1;
printf("Please enter %d numbers for the first list: ", n); //輸入第一條list並創建
build_a_list(&head, n);
n = rand() % 10 + 1;
printf("Please enter %d numbers for the second list: ", n); //輸入第二條list並插入第一條list中
for (i = 0; i < n; i++)
insert_to_list(&head);
printf("The merged list:\n");
print_list(head);
printf("But the initial list won't change.\n"); //並不會改變最初創建的initial list
clean_list(head);
}
void split_list() //將list分成奇數及偶數並印出
{
struct node *cur, *even = NULL, *odd = NULL;
for (cur = first; cur->data % 2 != 0 && cur->next != NULL; cur = cur->next) //找存偶數的第一個節點
;
if (cur->data % 2 != 0 && cur->next == NULL) {
printf("There is no even number in the list.");
return;
}
else
even = cur;
for (cur = first; cur->data % 2 == 0 && cur->next != NULL; cur = cur->next) //找存奇數的第一個節點
;
if (cur->data % 2 == 0 && cur->next == NULL) {
printf("There is no odd number in the list.");
return;
}
else
odd = cur;
cur = even;
printf("The even list:\n%d ", cur->data); //依序找出存偶數的節點並印出
while (cur->next != NULL) {
cur = cur->next;
while (cur->data % 2 != 0 && cur->next != NULL)
cur = cur->next;
if (cur->data % 2 == 0)
printf("%d ", cur->data);
else
break;
}
printf("\n");
cur = odd;
printf("The odd list:\n%d ", cur->data); //依序找出存奇數的節點並印出
while (cur->next != NULL) {
cur = cur->next;
while (cur->data % 2 == 0 && cur->next != NULL)
cur = cur->next;
if (cur->data % 2 != 0)
printf("%d ", cur->data);
else
break;
}
printf("\n");
}
沒有留言:
張貼留言