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
  • 大二必修 張信宏教授的資料結構
Made with Slides.com