Struct & Linked List
LAVI
Agenda
- Struct
- Linked List
- Traverse
- Insertion
- Deleting
- Circularly
- Doubly Linked List
Struct
struct <tag>{
member list
}variable list;
Struct
- tag
- struct 名字
- member-list
- struct 的成員列表
- variable list
- 此 struct 聲明的變數
Struct
struct student{
char name[5];
int age;
}st1, st2[100], *st3;
int main(){
st1.age = 19;
}
struct student{
char name[5];
int age;
};
int main(){
struct student st1, st2[100], *st3;
}
可以直接宣告
可以另外宣告
struct student st1;
strcpy(st1.name, "LAVI");
st1.age = 19;
student st1={
.name = "LAVI",
.age = 19,
};
一般寫法
進階寫法
初始化
#include <stdio.h>
#include <string.h>
struct student{
char name[5];
int age;
};
int main(){
struct student st1;
strcpy(st1.name, "LAVI");
st1.age = 19;
printf("%s %d\n", st1.name, st1.age);
return 0;
}
直接選取運算子( . )
#include <stdio.h>
#include <string.h>
struct student{
char name[5];
int age;
};
int main(){
struct student st1;
struct student *st1Ptr = &st1;
strcpy(st1.name, "LAVI");
st1.age = 19;
printf("st1: %s %d\n", st1.name, st1.age);
printf("st1Ptr->: %s %d\n", st1Ptr->name, st1Ptr->age);
printf("(*st1Ptr): %s %d\n", (*st1Ptr).name, (*st1Ptr).age);
printf("&st1: %s %d\n", (&st1)->name, (&st1)->age);
return 0;
}
間接選取運算子( -> )
Lab 0x0
小明是一位程式設計老師
他總共有 n 個學生、這學期考了 m 次上機考
今天小明想要當掉全班 1/2 個學生 你能幫他找出誰會被當嗎 owo
// input
4 <- 學生人數 (row)
5 <- 考試次數 (column)
Tom 99 80 75 88 92 <- 名字&分數
Ann 88 72 60 77 72
Bee 60 55 44 88 99
Amy 99 99 99 99 99
//output
Ann 88 72 60 77 72
Bee 60 55 44 88 99
0 < n < 64 , 1 < m < 10, name length < 10
Lab 0x0 Solution
struct Student{
char name[10];
int scores[10];
int totalscore;
}student[65];
int n, m;
int average = 0;
scanf("%d%d", &n, &m);
for(int i = 0 ; i < n ; i++){
scanf("%s", &student[i].name);
for(int j = 0 ; j < m ; j++){
scanf("%d", &student[i].scores[j]);
student[i].totalscore += student[i].scores[j];
average += student[i].scores[j];
}
}
average /= n;
Lab 0x0 Solution Code
#include <stdio.h>
struct Student{
char name[10];
int scores[10];
int totalscore;
}student[65];
int main(){
int n, m;
int average = 0;
scanf("%d%d", &n, &m);
for(int i = 0 ; i < n ; i++){
scanf("%s", &student[i].name);
for(int j = 0 ; j < m ; j++){
scanf("%d", &student[i].scores[j]);
student[i].totalscore += student[i].scores[j];
average += student[i].scores[j];
}
}
average /= n;
printf("\n");
for(int i = 0; i < n; i++){
if(student[i].totalscore < average){
printf("%s ", student[i].name);
for(int j = 0; j < m; j++){
printf("%d ", student[i].scores[j]);
}
printf("\n");
}
}
return 0;
}
Linked List
- memory allocation
-
配置指定大小的記憶體空間
- 配置的空間處於尚未初始化的狀態
- 動態的宣告記憶體空間
- 要多少開多少
malloc
int *dyn;
int arrlen1 = 5;
int arrlen2 = 2;
dyn = malloc( arrlen1 * arrlen2 * sizeof(int) );
- 釋放之前使用 malloc 所配置的記憶體空間
- memory leak
- 程式未釋放已不再使用的內部記憶體空間
- 用完記憶體後沒有 free 掉
- 在程式執行完後會自動把記憶體還回去
free
int *dyn;
int arrlen1 = 5;
int arrlen2 = 2;
free(dyn);
用 struct 實作 linked list
struct node{
int data; <- 資料成員
struct node *next; <- 鏈結成員 指向下一個節點的指標
}
指向下一個節點的位址
data
next
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node* list_pointer;
typedef struct struct list_node{
char data[5];
list_pointer link;
}ListNode;
創建一個 linked list 的 struct
int main(){
list_pointer ptr1 = NULL, ptr2 = NULL;
ptr1 = (list_pointer) malloc(sizeof(ListNode));
strcpy(ptr1->data, "CPC");
ptr1 -> link = NULL;
return 0;
}
NULL
data
next
CPC
第一個節點
新增節點
list_pointer create2(){
list_pointer first, second;
first = (list_pointer) malloc(sizeof(ListNode));
second = (list_pointer) malloc(sizeof(ListNode));
second-> link = NULL;
strcpy(second->data, "Mimmy");
strcpy(first->data, "LAVI");
first-> link = second;
return first;
}
data
next
LAVI
NULL
data
next
Mimmy
first
second
Lab 0x1
給你一個字元陣列 請用迴圈幫我把所有人依序串接起來
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
CPC
NULL
Jack
Hank
Jay
Mimmy
LAVI
CHA
Andy
yus
// output
CPC Jack Hank Jay Mimmy LAVI CHA yus Andy
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = NULL;
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
}
Lab 0x1 Solution
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node* list_pointer;
typedef struct list_node{
char data[10];
list_pointer link;
}ListNode;
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = NULL;
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
}
Lab 0x1 Solution Code
Traverse
遍歷
- 每個點只記自己下一個點的位址
- linked list 找點要遍歷
遍歷
int cnt = 0;
ListNode *node = head;
while(node->data != 5){
cnt++;
node = node->link;
}
printf("%d\n", cnt);
// output: 5
Lab 0x2
來玩躲貓貓 !
請找到 LAVI 排在整段鏈結串列中的第幾個
Tips: 請從 0 開始算哦
CPC
NULL
Jack
Hank
Jay
Mimmy
LAVI
CHA
Andy
yus
Lab 0x2 Solution
while(strcmp(node->data, "LAVI")){
cnt++;
node = node->link;
}
printf("%d\n", cnt);
Lab 0x2 Solution Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node* list_pointer;
typedef struct list_node{
char data[10];
list_pointer link;
}ListNode;
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = NULL;
int cnt = 0;
ListNode *node = head;
while(strcmp(node->data, "LAVI")){
cnt++;
node = node->link;
}
printf("%d\n", cnt);
}
Insertion
插入
- 遍歷找到要插入新節點的位址
- 更改前一節點的 link -> 新節點
- 將新節點的 link 指向原位址的節點
插入
list_pointer insert;
insert = (list_pointer) malloc(sizeof(ListNode));
insert->data = 9;
// insert->link = NULL;
list_pointer node = head;
while(node->data != 4){
node = node->link;
}
insert->link = node->link;
node->link = insert;
Lab 0x3
歡迎加入 CPC 的行列 owo
試著把你的名字接在 Mimmy 學姊和 LAVI 學姊之間並輸出
// output
Jack Hank Jay Mimmy <你的名字> LAVI CHA yus Andy
CPC
Jack
Hank
Jay
Mimmy
LAVI
CHA
Andy
yus
You
Lab 0x3 Solution
list_pointer insert;
insert = (list_pointer) malloc(sizeof(ListNode));
strcpy(insert->data, "ShinHung");
insert->link = NULL;
list_pointer node = head;
while(strcmp(node->data, "Mimmy")){
node = node->link;
}
insert->link = node->link;
node->link = insert;
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
Lab 0x3 Solution Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node* list_pointer;
typedef struct list_node{
char data[10];
list_pointer link;
}ListNode;
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = NULL;
list_pointer insert;
insert = (list_pointer) malloc(sizeof(ListNode));
strcpy(insert->data, "ShinHung");
insert->link = NULL;
list_pointer node = head;
while(strcmp(node->data, "Mimmy")){
node = node->link;
}
insert->link = node->link;
node->link = insert;
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
}
Deleting
刪除節點
- 遍歷找到要刪除節點的位址
- 更改前一節點的指標 -> 下一節點
- free 歸還被刪除之節點的記憶體空間
刪除
list_pointer edge = head, ptr = edge;
while(ptr->data != 9){
edge = ptr;
ptr = ptr->link;
}
edge->link = ptr->link;
free(ptr);
Lab 0x4
現在試試來把你自己刪掉 !
或是要刪其他人也可以啦 owo
// output
Jack Hank Jay Mimmy LAVI CHA yus Andy
CPC
Jack
Hank
Jay
Mimmy
LAVI
CHA
Andy
yus
You
free
Lab 0x4 Solution Code
list_pointer edge = head, ptr = edge;
while(strcmp(ptr->data, "ShinHung")){
edge = ptr;
ptr = ptr->link;
}
edge->link = ptr->link;
free(ptr);
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
Lab 0x4 Solution Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node* list_pointer;
typedef struct list_node{
char data[10];
list_pointer link;
}ListNode;
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = NULL;
list_pointer insert;
insert = (list_pointer) malloc(sizeof(ListNode));
strcpy(insert->data, "ShinHung");
insert->link = NULL;
list_pointer node = head;
while(strcmp(node->data, "Mimmy")){
node = node->link;
}
insert->link = node->link;
node->link = insert;
list_pointer edge = head, ptr = edge;
while(strcmp(ptr->data, "ShinHung")){
edge = ptr;
ptr = ptr->link;
}
edge->link = ptr->link;
free(ptr);
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
}
Circularly
循環
- 最後不接 NULL 改接 head
循環
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
head->data = 0;
ListNode *last = head, *now;
for(int i = 1; i < 9; i++){
now = malloc(sizeof(ListNode));
now->data = i;
last->link = now;
last = now;
}
last->link = head;
Lab 0x5
把鏈結串列頭尾連起來 讓大家停不下來 !
Lab 0x5 Solution
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = head;
Lab 0x5 Solution Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node* list_pointer;
typedef struct list_node{
char data[10];
list_pointer link;
}ListNode;
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->link = now;
last = now;
}
last->link = head;
for(ListNode *i = head; i != NULL; i = i->link){
printf("%s ", i->data);
}
printf("\n\n");
}
Doubly Linked List
雙向
- 左指標與右指標
- 右指標接下個節點
- 左指標接上個節點
雙向
typedef struct list_node *list_pointer;
typedef struct list_node{
int data;
list_pointer leftlink;
list_pointer rightlink;
}ListNode;
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
head->data = 0;
head->leftlink = NULL;
ListNode *last = head, *now;
for(int i = 1; i < 9; i++){
now = malloc(sizeof(ListNode));
now->data = i;
last->rightlink = now;
now->leftlink = last;
last = now;
}
last->rightlink = NULL;
插入
- 遍歷找到要插入新節點的位址
- 前一節點的右指標 -> 新節點
- 新節點的左指標 -> 前一節點
- 新節點的右指標 -> 下一節點
- 下一節點的左指標 -> 新節點
插入
list_pointer insert;
insert = (list_pointer) malloc(sizeof(ListNode));
insert->data = 9;
list_pointer node = head, ptr = head;
while(ptr->data != 3){
node = ptr;
ptr = ptr->rightlink;
}
insert->rightlink = node->rightlink;
node->rightlink->leftlink = insert;
insert->leftlink = node;
node->rightlink = insert;
刪除
- 遍歷找到要刪除節點的位址
- 前一節點的右指標 -> 被刪除節點之下一節點
- 下一節點的左指標 -> 前一節點
- free 歸還被刪除之節點的記憶體空間
刪除
list_pointer edge = head, pt = edge;
while(pt->data != 9){
edge = pt;
pt = pt->rightlink;
}
edge->rightlink = pt->rightlink;
pt->rightlink->leftlink = edge;
free(pt);
Lab 0x6
把大家手牽手左右牽起來~
// output
from begining to end
CPC Jack Hank Jay Mimmy LAVI CHA yus Andy
from end to begining
Andy yus CHA LAVI Mimmy Jay Hank Jack CPC
NULL
Hank
Jay
Mimmy
LAVI
CHA
Andy
yus
Jack
Hank
Jay
Mimmy
CPC
Andy
yus
CHA
LAVI
Lab 0x6 Solution
ListNode *final = NULL;
final = malloc(sizeof(ListNode));
strcpy(final->data, "CPC");
final->leftlink = NULL;
ListNode *last = final, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->rightlink = now;
now->leftlink = last;
last = now;
}
last->rightlink = NULL;
Lab 0x6 Solution Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct list_node *list_pointer;
typedef struct list_node{
char data[10];
list_pointer leftlink;
list_pointer rightlink;
}ListNode;
char name[][10] = {"Jack", "Hank", "Jay", "Mimmy", "LAVI", "CHA", "yus", "Andy"};
int main(){
ListNode *head = NULL;
head = malloc(sizeof(ListNode));
strcpy(head->data, "CPC");
head->leftlink = NULL;
ListNode *last = head, *now;
for(int i = 0; i < 8; i++){
now = malloc(sizeof(ListNode));
strcpy(now->data, name[i]);
last->rightlink = now;
now->leftlink = last;
last = now;
}
last->rightlink = NULL;
printf("from begining to end\n");
for(ListNode *i = final; i != NULL; i = i->rightlink){
printf("%s ", i->data);
}
printf("\n\nfrom end to begining\n");
for(ListNode *i = last; i != NULL; i = i->leftlink){
printf("%s ", i->data);
}
}
UVA 11988
Broken Keyboard
你有一個破損的鍵盤,鍵盤上的所有鍵都可以正常工作
但有時 Home 鍵 ' [ ' 或者 End 鍵 ' ] ' 會自動按下
然而你並不知道鍵盤存在這一問題就繼續專心打稿子
當你開啟顯示器之後,展現在你面前的是一段悲劇的文字
現在你的任務是在開啟顯示器之前計算出這段悲劇文字
UVA 11988
Input
每組資料佔一行,包含不超過 100000 個字元
輸入結束標誌為檔案結束符 EOF
Output
對於每組資料,輸出一行,即螢幕上的悲劇文字
UVA 11988
// Sample Input
This_is_a_[Beiju]_text
[[]][][]Happy_Birthday_to_Tsinghua_University
// Sample Output
BeijuThis_is_a__text
Happy_Birthday_to_Tsinghua_University
UVA 11988 Solution Code
#include<stdio.h>
#include<stdlib.h>
typedef struct list_node *list_pointer;
typedef struct list_node{
char data;
list_pointer link;
}ListNode;
int main(){
char str[100000+5];
ListNode *head, *tail, *now;
while(scanf("%s", str) != EOF){
int begin;
for(begin = 0; str[begin] != '\0'; begin++){
if((str[begin] != '[') && str[begin] != ']'){
ListNode *new = malloc(sizeof(ListNode));
new->data = str[begin];
new->link = NULL;
head = tail = now = new;
break;
}
}
int i;
for(i = begin+1; str[i] != '\0'; i++){
if(str[i] == '['){
now = NULL;
}
else if(str[i] == ']'){
now = tail;
}
else{
ListNode *new = malloc(sizeof(ListNode));
new->data = str[i];
if(now == NULL){
new->link = head;
head = now = new;
}
else if(now == tail){
new->link = NULL;
now->link = new;
tail = now = new;
}
else{
new->link = now->link;
now->link = new;
now = new;
}
}
}
ListNode *j;
for(j = head; j != NULL; j = j->link){
printf("%c", j->data);
}
printf("\n");
}
return 0;
}
特別感謝
- 林子傑學長的 CPC Training
- 大二必修 張信宏教授的資料結構
Struct & Linked List
By lavi_0724
Struct & Linked List
- 183