升序鏈表的基本操作

// List1.cpp : Defines the entry point for the console application.
//
/*
   C語言下的升序鏈表的基本操作  List1.cpp
   -------------------------------------
   作者:     Software Engineering @ HIT
              1093710210  Alex
   時間:     2010.9.10
   -------------------------------------
*/
//黃虎傑院長在數據結構基礎與算法課上留的一個小練習。。。好幾天了,一直沒寫,感覺不會太難,沒想到一寫還真是把自己整的挺蒙的,還要多練啊
//不過寫鏈表的過程中學到了很多經驗。。不要迷信網絡。。感覺好亂。。還是準備一張白紙一支筆。。自己畫得明白= =
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
struct List
{
    int data;
    struct List *next;
};
void menu();
struct List *Create(struct List *h) ;     //創建和插入升序鏈表
void Display(struct List *h);             //輸出鏈表信息
struct List *Delete_all(struct List *h);  //刪除整個鏈表
struct List *Delete(struct List *h , int xdata) ;  //刪除鏈表中結點
struct List *Search(struct List *h , int xdata) ;  //查找某節點位置,本例中返回了其地址
struct List *Revers(struct List *h) ;              //實現鏈表的逆序
int main(int argc, char* argv[])
{
    int choice,i =0;
    struct List *position,*MyList = NULL;
    int xdata;
    menu();
    while (1)
    {
        printf("請輸入操作:  ");
        scanf("%d",&choice);
        switch (choice)
        {
        case 1:
            printf("Please input the node: /n");
            MyList = Create( MyList);
            break;
        case 2:
            printf("Please input the node you want to delete: /n");
            scanf("%d",&xdata);
            MyList = Delete( MyList,xdata);
            break;
        case 3:
            printf("Please input the node you want to locate: /n");
            scanf("%d",&xdata);
            position = Search(MyList,xdata);
            printf("the node position is %d",position);
            break;
        case 4:
            Display(MyList);
            break;
        case 5:
            MyList = Revers( MyList);
            printf("The links reversed is :/n");
            Display(MyList);
            break;
        case 6:
            MyList = Delete_all(MyList);
            printf("Link deleted ! /n");
            break;
        default:
            printf("wrong!");
        }
    }
    return 0;
}
void menu()
{
    printf("單向升序鏈表的操作/n");
    printf("-----------------------------------------/n");
    printf("1 -> 創建升序鏈表鏈表或插入節點升序鏈表中/n");
    printf("2 -> 刪除鏈表中的某個節點/n");
    printf("3 -> 返回某個節點的地址指針/n");
    printf("4 -> 輸出線性鏈表/n");
    printf("5 -> 實現單向鏈表逆序/n");
    printf("6 -> 刪除整個線性表/n");
}
/*
函數功能:升序輸入鏈表函數
函數參數:結構體指針
返回值 : 結構體指針
*/
struct List *Create(struct List *h)
{
    struct List *newpr = NULL;
    struct List *temp = h;
    struct List *flag = NULL;
    int data;
    newpr = (struct List *)malloc(sizeof (struct List));
    if (newpr == NULL)         //用於檢查是否申請動態空間成功
    {
        printf("memory error");
        exit(0);
    }
    scanf("%d",&data);
    newpr->data = data;
    newpr->next = NULL;

    if (h == NULL)
        h = newpr;
    else
    {
        while (temp->next != NULL && temp->data <= data ) //老師上課用的<,我感覺還是應該用<=這樣可以解決重複輸入相同data無效的問題
        {
            flag = temp;        //flag用於記錄合適的插入點前的位置
            temp = temp->next;
        }
        if (temp->data >data) //用於檢查時否在兩個值之間,可以看出是否到了鏈表的末尾
        {
            if (temp == h) //說明在表頭前插入數據,產生新的表頭
            {
                newpr->next = h ;
                h = newpr ;
            }
            else
            {
                temp = flag;                    //把當前的位置前移一下,移到插入點前面
                newpr->next = temp->next;
                temp->next = newpr;
            }
        }
        else         //在表末插入
        {
            temp->next =newpr;
        }
    }
    return h;
}

/*
函數功能:輸出線性表
函數參數:結構體指針
返回值 : void
*/
void Display(struct List *h)
{
    struct List *p = h;
    int counter = 1;
    printf("Position:   Data /n");
    while (p != NULL)
    {
        printf("   %d    " ,counter);
        printf(":    %d/n", p->data );
        counter++;
        p = p->next;
    }
}
/*
函數功能:刪除某個結點
函數參數:結構體指針,要刪除節點數據int
返回值 : 結構體指針
*/
struct List *Delete(struct List *h , int xdata)
{
    struct List *temp = h;
    struct List *flag = h;
    if ( h == NULL)
    {
        printf("no link !");
        return (h);
    }
    while (temp->data != xdata && temp->next !=NULL)
    {
        flag = temp;
        temp = temp->next;
    }
    if (xdata == temp->data) //檢查是到了末尾還是已經找到相應節點
    {
        if (temp == h) //首節點的情況
        {
            h = temp->next;
        }
        else
        {
            flag->next=temp->next;
        }
        free (temp);
    }
    else
        printf("NO NODE!/n");
    return h;
}
/*
函數功能:返回某節點的地址
函數參數:結構體指針,要查找節點數據int
返回值 : 結構體指針
*/
struct List *Search(struct List *h , int xdata)
{
    struct List *temp = h;
    if ( h == NULL)
    {
        printf("no link !");
        return (h);
    }
    while (temp->data != xdata && temp->next !=NULL)
    {
        temp = temp->next;
    }
    if (xdata == temp->data) //檢查是到了末尾還是已經找到相應節點
        return temp;
    else
        printf("NO Location!/n");
    return temp;
}
/*
函數功能:單向鏈表的逆序
函數參數:結構體指針
返回值 : 結構體指針
*/
struct List *Revers(struct List *h)
{
    struct List *back,*p,*newhead = NULL;
    p = h;
    while ( p != NULL)
    {
        back = p->next;       //記錄當前節點的下一位置,以防鏈表丟失
        p->next = newhead ;   //當前節點開始指向前一個節點,此時的newhead初始化一定爲NULL
        newhead = p ;         //newhead指針緊跟着p向後移,一直到最後p指向NULL了,此時newhead爲逆序的首結點
        p= back;              //找到下一個節點
    }
    return newhead;
}
//感受:從網上看了一個,分明是弄錯指針p後移時,沒有記錄下一節點的位置,造成鏈表的斷開
//他的做法是  back = p;
//            p->next = newhead ;
//            newhead = p ;
//            p= back->next;   這樣的話表面上是back記錄了下一個節點,實際上他指向的P的next已經被修改爲NULL,使得最後一行語句無效
struct List *Delete_all(struct List *h)
{
    struct List *temp = NULL;
    while (h!= NULL)
    {
        temp = h;
        h=temp->next;
        free(temp);
    }
    return h;
}


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