數據結構之鏈表的使用【C語言】

鏈表在幾種數據結構中算是比較簡單的,操作也比較簡單。鏈表分爲單向、雙向、循環鏈表,其中單向鏈表是所有鏈表的基礎。結合一個簡單的例子,用C語 言實踐單向鏈表的創建、修改、刪除操作。在實踐的過程中,學習了C語言關於scanf的使用技巧:在scanf使用多次時,需要使用 fflush(stdin)來清空緩衝區,最好每次使用後,就刷新一次,以免出現不確定的輸入的問題。

學生信息:姓名、年齡。

操作:1、增加;2、修改;3、刪除;4、查詢;5、退出。其中查詢使用strstr()函數,實現部分匹配查找。順序查詢算法複雜度爲O(n)。

缺點:只有順序添加節點功能,沒有隨機添加節點功能。

代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NAMEMAX 40
#define SUCCESS 1
#define FAIL 0

struct student
{
    char studentName[NAMEMAX];
    unsigned int studentAge;
    struct student* next;
};
typedef struct student node;
typedef struct student* pNode;

static int studentNumber;

/********* 函數聲明 開始 *********/
pNode add_student(pNode head);
pNode find_lastNode(pNode head);
void modify_student(pNode head);
pNode delete_student(pNode head);
int search_student(pNode head);
void quit_student(pNode head);
/********* 函數聲明 結束 *********/

/***
 * 查找最後一個節點
 */
pNode find_lastNode(pNode head)
{
    pNode tempPNode;

    tempPNode = head;
    while(tempPNode->next != NULL)
    {
        tempPNode = tempPNode->next;
    }

    return tempPNode;
}

/***
 * 顯示學生個人信息
 */
void show_student_information(pNode node)
{
    printf("姓名:%s\n",node->studentName);
    printf("年齡:%u\n",node->studentAge);
}

/**
 * 增加學生信息
 * 創建單向鏈表
 * head:鏈表頭指針
 */
pNode add_student(pNode head)
{
    char tempName[NAMEMAX];//學生姓名臨時變量
    unsigned int tempAge;//學生年齡臨時變量
    pNode tempPNode;
    pNode tempPPreNode;
    char isAdd;

    printf("\n************************\n");
    printf("      增加學生信息\n");
    printf("************************\n");
    printf("請輸入學生姓名: ");
    scanf("%s",tempName);//輸入姓名
    printf("請輸入學生年齡: ");
    while((scanf("%u",&tempAge) !=1) || tempAge <=0)//輸入年齡
    {
        printf("請輸入正確的年齡(大於0的整數): ");
    }
    printf("************************\n");
    printf("學生信息\n");
    printf("姓名:%s\n", tempName);
    printf("年齡:%u\n", tempAge);
    printf("是否增加(Y/N): ");

    fflush(stdin);//刷新緩衝區
    while((scanf("%c",&isAdd) != 1) || (isAdd != 'Y' && isAdd != 'y' && isAdd != 'N' && isAdd != 'n'))//是否增加
    {
        printf("請輸入Y或者y或者N或者n!\n");
        printf("是否增加(Y/N): ");
        //刷新緩衝區
        fflush(stdin);
    }
    if(isAdd == 'Y' || isAdd == 'y')
    {
        if(head == NULL)//無節點
        {
            head = (pNode)malloc(sizeof(node));
            strcpy(head->studentName, tempName);
            head->studentAge = tempAge;
            head->next = NULL;
        }
        else//有節點
        {
            tempPNode = (pNode)malloc(sizeof(node));
            strcpy(tempPNode->studentName, tempName);
            tempPNode->studentAge = tempAge;
            tempPNode->next = NULL;

            tempPPreNode = find_lastNode(head);
            tempPPreNode->next = tempPNode;
        }
        studentNumber ++;
        printf("增加學生信息成功,");
    }
    else
    {
        printf("增加學生信息失敗,");
    }

    printf("返回主菜單\n\n");

    return head;
}

/**
 * 修改學生信息
 * 順序查找鏈表
 */
void modify_student(pNode head)
{
    unsigned int index = 0;//選中學生的序號
    unsigned int tmpIndex = 0;//臨時變量
    pNode tmpNode;//節點臨時變量
    char tmpName[NAMEMAX];
    unsigned int tmpAge = 0;
    char isAdd;

    if(search_student(head))
    {
        printf("請選擇序號:");

        while((scanf("%u",&index) != 1) || index == 0)
        {
            printf("請輸入大於0的整數!\n");
            printf("請選擇序號:");
            fflush(stdin);
        }

        tmpNode = head;

        while(tmpNode)
        {
            if(strstr(tmpNode->studentName,tmpName) != NULL)/*查找成功*/
            {
                tmpIndex++;
                if(tmpIndex == index)//找到
                {
                    break;
                }
                else//未找到
                {
                    tmpNode = tmpNode->next;
                }
            }
        }

        if(tmpIndex != 0 && tmpIndex == index)//找到
        {
            printf("選中的學生信息:\n");
            show_student_information(tmpNode);

            printf("新信息:\n");
            printf("姓名:");
            scanf("%s",tmpName);
            printf("年齡:");

            while((scanf("%u",&tmpAge) != 1) || tmpAge == 0)
            {
                printf("請輸入大於0的整數!\n");
                printf("年齡:");
                fflush(stdin);
            }

            printf("是否修改(Y/N): ");

            fflush(stdin);//刷新緩衝區
            while((scanf("%c",&isAdd) != 1) || (isAdd != 'Y' && isAdd != 'y' && isAdd != 'N' && isAdd != 'n'))//是否增加
            {
                printf("請輸入Y或者y或者N或者n!\n");
                printf("是否修改(Y/N): ");
                //刷新緩衝區
                fflush(stdin);
            }

            if(isAdd == 'Y' || isAdd == 'y')//修改
            {
                strcpy(tmpNode->studentName, tmpName);
                tmpNode->studentAge = tmpAge;
                printf("已修改!返回主菜單。\n");
            }
            else//不修改
            {
                printf("未修改!返回主菜單。\n");
            }

        }
        else//未找到
        {
            printf("未修改!返回主菜單。\n");
            return;
        }
    }

}

/***
 * 按照姓名模糊查找,並刪除相關學生信息
 * 刪除鏈表節點
 */
pNode delete_student(pNode head)
{
    unsigned int index = 0;//選中學生的序號
    unsigned int tmpIndex = 0;//臨時變量
    pNode tmpNode = NULL;//節點臨時變量
    pNode tmpPreNode = NULL;//要刪除的節點的前一個節點臨時變量
    char tmpName[NAMEMAX];
    char isDel;

    if(search_student(head))
    {
        printf("請選擇序號:");

        while((scanf("%u",&index) != 1) || index == 0)
        {
            printf("請輸入大於0的整數!\n");
            printf("請選擇序號:");
            fflush(stdin);
        }

        tmpNode = head;

        while(tmpNode)
        {
            if(strstr(tmpNode->studentName,tmpName) != NULL)/*查找成功*/
            {
                tmpIndex++;
                if(tmpIndex == index)//找到
                {
                    break;
                }
                else//未找到
                {
                    tmpPreNode = tmpNode;
                    tmpNode = tmpNode->next;
                }
            }
        }

        if(tmpIndex !=0 && tmpIndex == index)//找到
        {
            printf("是否刪除(Y/N): ");

            fflush(stdin);//刷新緩衝區
            while((scanf("%c",&isDel) != 1) || (isDel != 'Y' && isDel != 'y' && isDel != 'N' && isDel != 'n'))//是否增加
            {
                printf("請輸入Y或者y或者N或者n!\n");
                printf("是否刪除(Y/N): ");
                //刷新緩衝區
                fflush(stdin);
            }

            if(isDel == 'Y' || isDel == 'y')//刪除
            {
                if(tmpNode == head)//如果刪除的節點爲頭結點
                {
                    head = head->next;
                }
                else if(tmpNode->next != NULL)//刪除的節點在中間
                {
                    tmpPreNode->next = tmpNode->next;
                    tmpNode->next = NULL;
                }
                else if(tmpNode->next == NULL)//刪除的節點在末尾
                {
                    tmpPreNode->next = NULL;

                }
                free(tmpNode);
                tmpNode == NULL;
                printf("刪除成功!返回主菜單。\n");
                studentNumber --;
            }
            else//不刪除
            {
                printf("未刪除!返回主菜單。\n");
            }
        }
        else//未找到
        {
            printf("未找到!返回主菜單。\n");
        }
    }

    return head;
}

/***
 * 按照姓名模糊查找
 * 順序查找鏈表
 */
int search_student(pNode head)
{
    //測試使用
    pNode tmpNode;
    int tmpIndex = 0;
    char tmpName[NAMEMAX];//學生姓名臨時變量

    if(head == NULL)
    {
        printf("沒有學生信息,請添加!返回主菜單。\n");
        return FAIL;
    }

    printf("\n************************\n");
    printf("輸入學生姓名【模糊查找】:\n");

    fflush(stdin);

    scanf("%s",tmpName);

    tmpNode = head;

    while(tmpNode)
    {
        if(strstr(tmpNode->studentName,tmpName) != NULL)/*查找成功*/
        {
            tmpIndex++;
            printf("%d:\n",tmpIndex);
            show_student_information(tmpNode);
        }
        tmpNode = tmpNode->next;
    }

    if(tmpIndex == 0)
    {
        printf("沒有查找到名字中包含%s的學生!\n",tmpName);
        printf("\n************************\n");
        return FAIL;
    }
    printf("\n************************\n");
    return SUCCESS;
}

/**
 * 退出系統,刪除所有學生信息
 * 刪除鏈表
 */
void quit_student(pNode head)
{
    pNode tmpNode1 = NULL;
    pNode tmpNode2 = NULL;

    if(head == NULL)
    {
        return;
    }

    tmpNode1 = head;

    while(tmpNode1)
    {
        tmpNode2 = tmpNode1->next;
        free(tmpNode1);
        tmpNode1 = tmpNode2;
    }
    head = NULL;
}

/*****
 * 主程序
 */
int main(void)
{
    int choice;//用戶選項
    int isContinue;//是否繼續
    pNode head;//鏈表頭

    choice = 0;
    studentNumber = 0;
    head = NULL;
    isContinue = 1;

    do{
        printf("************************\n");
        printf("歡迎使用學生信息管理系統\n");
        printf("************************\n");
        printf("主菜單:\n");
        printf("1.增加學生信息\n");
        printf("2.修改學生信息\n");
        printf("3.刪除學生信息\n");
        printf("4.查詢學生信息\n");
        printf("5.退出系統\n");
        printf("------------------------\n");
        printf("已有%d名學生信息\n",studentNumber);
        printf("------------------------\n");
        printf("請輸入菜單選項(1-5): ");

        while((scanf("%d",&choice) != 1) || (choice > 5) || (choice < 1))
        {
            printf("警告:請輸入1-5整數!\n");
            printf("請輸入菜單選項(1-5): ");
            fflush(stdin);//刷新緩衝區
        }

        switch(choice)
        {
        case 1://增加
            head = add_student(head);
            break;
        case 2://修改
            modify_student(head);
            break;
        case 3://刪除
            head = delete_student(head);
            break;
        case 4://查詢
            search_student(head);
            break;
        case 5://退出系統
            quit_student(head);
            isContinue = 2;
            break;
        default://異常錯誤,暫無處理
            printf("出現異常錯誤,退出系統!\n");
            break;
        }
    }while(isContinue == 1);

    return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章