鏈表的基本操作

總結一下鏈表的一些基本操作:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define N 12
#define M 20
typedef int elemType;


//定義單鏈表節點類型
typedef struct Node
{
    elemType element;
    Node *next;
}Node;

//初始化線性表,即置單鏈表的表頭指針爲空
void initList(Node **pNode)
{
    *pNode = (Node *) malloc(sizeof(Node));
    (*pNode) ->next = NULL;
    printf("initList 函數執行,初始化成功\n");

}

//創建線性表,此函數輸入負數終止讀取數據
Node *creatList(Node *pHead)
{
    Node *p1;
    Node *p2 = NULL;
    p1= (Node *)malloc(sizeof(Node)); //申請新節點
    if (p1 == NULL || p2 == NULL)
    {
        printf("內存分配失敗\n");
        exit (0);
    }
    memset(p1, 0, sizeof (Node));

    scanf("%d", &p1->element); //輸入新節點
    p1->next = NULL;  //新節點的指針置空。
    while(p1->element > 0)
    {
        if(pHead == NULL)  //空表,接入表頭
            pHead = p1;
        else
            p2->next = p1;  //非空表,接入表尾
        p2 = p1;
        p1 = (Node *) malloc (sizeof (Node)); //在重新申請一個節點
        if (p1 == NULL || p2 == NULL)
        {
            printf("內存分配失敗\n");
            exit (0);
        }
        memset(p1, 0, sizeof(Node));
        scanf("%d",&p1->element);
        p1->next = NULL;

    }   
    printf("creatLise函數執行,鏈表創建成功\n");
    return pHead;
}

//打印鏈表,鏈表的遍歷
void printList (Node *pHead)
{
    if(pHead == NULL)
        printf("PrintList 函數執行,鏈表爲空");
    else
    {
        while (NULL != pHead)
        {
            printf("%5d",pHead->element );
            pHead = pHead->next;
        }
        printf("\n");

    }
}

//清除線性表L中的所以元素,即釋放單鏈表L中
//的所有節點,使之成爲一個空表
void clearList(Node *pHead)
{
    Node* pNext; //定義一個與pHead相鄰節點

    if (pHead == NULL)
    {
        printf("clearList函數執行,鏈表爲空\n");
        return; 
    }
    while(pHead->next != NULL)
    {
        pNext = pHead -> next; //保存下一節點的指針
        free(pHead);
        pHead = pNext;  //表頭下移
    }
    printf("clesrList 函數執行,鏈表已經清除\n");
}

//返回單鏈表的長度
int sizeList(Node *pHead)
{
    int size = 0;
    while(pHead != NULL)
    {
        size ++;  //遍歷鏈表大小實際比實際鏈表小1
        pHead = pHead->next;
    }
    printf("sizeList函數執行,鏈表長度:%d\n",size );
    return size;
}

//檢測鏈表是否爲空,若空則返回1,否則返回0
int isEmptyList(Node*pHead)
{
    if(pHead == NULL)
    {
        printf("isEmptyList函數執行,鏈表爲空\n");
        return 1;
    }
    printf("isEmptyList函數執行,鏈表爲空\n");
    return 0;
}

//返回單鏈表中第pos個節點的元素,若pos超出範圍,則停止程序運行
elemType getElemnt(Node *pHead, int pos)
{
    int i = 0;
    if(pos < i)
    {
        printf("pos值非法\n");
        return 0;
    }
    if (pHead == NULL)
    {
        printf("getElement函數執行,鏈表爲空\n");
        return 0;
        //exit (1);  //退出程序
    }
    while(pHead != NULL)
    {
        ++i;
        if(i == pos)
            break;
        pHead = pHead->next; //轉移到下一個節點
    }
    if (i < pos)
    {
        printf("getElement函數執行,pos值超出鏈表長度\n");
        return 0;
    }
    return (pHead->element);

}

//從單鏈表中查找鏈表具有給定值X的第一個元素,
//若查找成功則返回該節點data域的存儲地址,否則返回NULL。
elemType *getElementAddr(Node * pHead, elemType x)
{
    if (pHead == NULL)
    {
        printf("getElementAddr函數執行,鏈表爲空\n");
        return NULL;
    }
    if (x < 0)
    {
        printf("getElementAddr函數執行,給定的x值不合法\n");
        return NULL;
    }
    //判斷是否到鏈表末尾,以及是否存在所要查找的元素
    while((pHead->element != x ) && (pHead->next != NULL))
    {
        pHead = pHead->next;
    }
    if (pHead->element == x)
        //printf("gerElementAddr函數執行,元素%d的地址爲: 0x%x\n",x,&(pHead->element));
    return &(pHead->element);
}

//把單鏈表中第pos個節點的元素替換爲x,若修改成功返回1,否則返回0
int modifyElem(Node *pNode, int pos, elemType x)
{
    Node *pHead;
    pHead = pNode;
    int i = 0 ;
    if (pHead == NULL)
    {
        printf("modifyElem函數執行,鏈表爲空\n");
        return 0;
    }
    if(pos < 1)
    {
        printf("modifyElem函數執行,pos值非法\n");
        return 0;
    }
    while(pHead != NULL)
    {
        ++i;
        if (pos == i)
            break;
        pHead = pHead->next;
    }
    if (i < pos)
    {
        printf("modifyElem函數執行,pos值超出鏈表長度\n");
        return 0;
    }
    pNode = pHead->next;
    pNode->element = x;
    //printf("modeifyElemAddr函數執行\n");
    return 1;
}


//向單鏈表的表頭插入一個元素
int insertHeadList(Node **pNode,elemType insertElem)
{
    Node *pInsert;
    pInsert = (Node *) malloc (sizeof (Node));
    memset(pInsert,0,sizeof(Node));
    pInsert->element = insertElem;
    pInsert->next = *pNode;
    *pNode = pInsert;
    printf("insertHeadLise函數執行,向表頭插入元素成功\n");
    return 1;
}

//向單鏈表末尾添加一個元素
int insertLastList (Node **pNode, elemType insertElem)
{
    Node *pInsert;
    Node *pHead;
    Node *ptemp; //定義一個臨時鏈表來存放第一個節點。

    pHead = *pNode;
    ptemp = pHead;
    pInsert = (Node *)malloc(sizeof(Node));
    memset(pInsert, 0 ,sizeof(Node));
    pInsert->element = insertElem;

    while(pHead->next != NULL)
    {
        pHead= pHead->next; //找到表末尾
    }
    pHead->next = pInsert;
    *pNode = ptemp;
    printf("insertLastLisr函數執行成功,想鏈表末尾插入元素成功\n");
    return 1;
}

//向有序單鏈表中插入元素,不改變鏈表的有序性
int insertOrderList(Node **pNode, elemType insertElem)
{
    Node *pHead, *ptemp = NULL, *pInsert;
    pHead = *pNode;
    pInsert = (Node *)malloc(sizeof(Node)); //申請一個新的節點
    if(pInsert == NULL)
    {
        printf("內存分配失敗,結束程序\n");
        exit(1);
    }
    pInsert->element = insertElem;

    //把新節點插入到表頭中
    if (pHead == NULL || insertElem < pHead->element)
    {
        pInsert->next = pHead;
        *pNode = pInsert;
        return 1;
    }
    //順序查找,找出insertElem的插入位置
    while(pHead != NULL)
    {
        if (insertElem < pHead->element)
            break;
        else
        {
            ptemp = pHead;
            pHead = pHead->next;
        }

    }

    //把x節點插入到ptemp與pHead之間
    pInsert->next = pHead;
    ptemp->next = pInsert;

    return 1;

}

//從單鏈表中刪除表頭節點,並把該節點
//的值返回,若刪除失敗則停止程序運行
elemType deleteFirstList(Node *pHead)
{
    elemType temp;
    Node *pNode;
    pNode = pHead; //暫存表頭節點指針,以便回收
    if (pHead == NULL)
    {
        printf("單鏈表爲空,退出程序\n");
        exit (1);
    }
    pHead = pHead->next; //使表頭指針指向第二個節點
    temp = pNode->element; //暫存原表頭元素,以便返回
    free(pNode);  //回收被刪除的表頭數據
    return temp; //返回第一個節點的值
}

//從單鏈表中刪除結尾節點並返回它的值,若刪除失敗則停止程序運行
elemType deleteLastList( Node *pHead)
{
    Node *pNode, *ptemp = NULL;
    elemType lastelement;
    pNode = pHead; //指向表頭節點
    if (pHead == NULL)
    {
        printf("鏈表爲空,退出程序\n");
        exit (1);
    }

    while (pNode ->next != NULL)
    {
        ptemp = pNode;
        pNode = pNode->next;  //查找鏈表末尾
    }

    //若單鏈表中只有一個節點,則只需要修改表頭指針
    if (ptemp == NULL)
        pHead = pHead->next;
    //刪除表尾節點
    else 
        ptemp->next = NULL;
    //暫存表尾元素,以便返回
    lastelement = pNode->element;
    free(pNode);
    return lastelement;  //返回表尾元素值
}

//從單鏈表中刪除第pos個節點,並返回它的值,若刪除失敗接受程序運行
elemType deletePosList (Node *pHead, int pos)
{
    int i = 0;
    Node *pNode, *ptemp = NULL;
    pNode = pHead;
    elemType poselement;
    if (pNode == NULL || pos <= 0)
    {
        printf("單鏈表爲空或者pos值非法\n");
        exit (1);
    }

    /*從單鏈表中找到第pos個節點*/
    while(pNode != NULL)
    {
        i++;
        if(i = pos)
            break;
        ptemp = pNode;
        pNode = pNode->next;

    }

    if(pNode == NULL)
    {
        printf("pos值非法,退出程序\n"); //鏈表中不存在第pos個節點
        exit(1);
    }
    //pos =1,刪除表頭節點
    if (pos == 1)
        pHead = pHead->next;
    /* 否則刪除非表頭結點,此時cp指向該結點,ap指向前驅結點 */
    else
        ptemp->next = pNode->next;

    poselement = pNode->element;
    free(pNode);
    return poselement;

}

//找到第index個元素,返回節點
Node * findnode( Node *phead, int index)
{
    if(!phead) return NULL;
    Node * pnode = phead;
    while (index --)
    {
        pnode = pnode->next;
        if (!pnode)
            return NULL;

    }
    return pnode;
}

//找到前驅節點
Node * find_preNode(Node *phead, Node *pnode)
{
    if(!pnode) return NULL;
    Node *preNode = phead;
    while (preNode)
    {
        if(preNode->next == pnode)
            return preNode;
        preNode = preNode->next;
    }
    return NULL;
}

//交換鏈表中的兩個元素
void swipList(Node **pHead, int i, int j)
{
    if(!pHead) return;
    //找出節點
    Node *pnode1 = findnode(*pHead, i);
    Node *pnode2 = findnode(*pHead,j);
    //找出前驅節點
    Node *pre1 = find_preNode(*pHead, pnode1);
    Node *pre2 = find_preNode(*pHead, pnode2);

    //相鄰的情況
    Node *pBefore = NULL, *pAfter = NULL, *pPre = NULL;
    if (pre2 == pnode1)
    {
        pBefore = pnode1;
        pAfter = pnode2;
        pPre = pre1;
    }
    if (pre1 == pnode2)
    {
        pBefore = pnode2;
        pAfter = pnode1;
        pPre = pre2;
    }
    if (pre2 == pnode1 ||pre1 == pnode2)
    {
        pPre->next = pAfter;
        pBefore->next = pAfter ->next;
        pAfter->next = pBefore;
    }
    else
    {
        //不相鄰的情況
        Node *pnext1 = pnode1 ->next;
        Node *pnext2 = pnode2->next;
        pnode1->next = pnode2->next;
        pre1->next = pnode2;
        pre2->next = pnode1;
        pnode2->next = pnext1;
    }


}

//鏈表的排序
void fastsort(Node **phead, Node *end)
{
    Node *right;
    Node **left_walk, **right_walk;
    Node *pivot, *old;
    int count, left_count, riht_count;
    if(*phead == end)
        return;
    do 
    {
        pivot = *phead;
        left_walk = phead;
        right_walk = &right;
        left_count = riht_count = 0;
        //取第一個節點作爲比較的基準點,小於基準點的在左面的子鏈表中,
        //大於基準的在右邊的子鏈表中
        for (old = (*phead)->next; old != end; old = old ->next)
        {
            if (old->element < pivot->element)
            {
                //小於基準,加入到左邊的子鏈表,繼續比較
                ++ left_count;
                *left_walk = old; //把該節點加入到左邊的鏈表中
                left_walk = &(old->next);

            }
            else   //大於基準,加入到右邊的子鏈表,繼續比較
            {
                ++riht_count;
                *right_walk = old;
                right_walk = &( old->next);

            }
        }


        //合併鏈表
        *right_walk = end; //結束右鏈表
        *left_walk = pivot; //把基準鏈表置於正確位置
        pivot->next = right; //鏈表合併

        //對較小的子鏈表進行快速排序,較大的子鏈表進行迭代排序
        if (left_walk > right_walk)
        {
            fastsort( &(pivot->next), end);
            end = pivot;
            count = left_count;
        }
        else
        {
            fastsort(phead, pivot);
            phead = &(pivot ->next);
            count = riht_count;
        }

    } while (count >1 );

}

int main()
{
    int a[N];
    int i;
    Node *p , *h , *s;

    initList(&h);
    p = h;


    srand(time(NULL));
    //產生隨機數組
    for ( i =0; i < N; i++)
    {
        a[i]=rand() % M + 1;
    }
    printf("隨機數序列爲:\n");
    for (int i = 0; i < N; i++)
    {
        printf("%5d",a[i]);
        //insertLastList( h, a[i]);
    }
    printf("\n");



    //利用數組初始化鏈表
    for (int i = 0; i < N; i++)
    {
        s = (Node *)malloc(sizeof(Node));  //申請一個新節點
        memset(s, 0, sizeof(Node));
        s->element = a[i];
        p->next = s;
        p = s;
    }
    p->next = NULL;

    Node * head = h->next;

    int pos = 11;
    int k = getElemnt(head,pos);
    printf("第%d個元素爲:%d\n",pos,k);

    printf("鏈表:\n");
    printList(head); //打印鏈表

    modifyElem(head, 2, 8);
    printf("將位置3元素替換成8之後的鏈表:\n");
    printList(head); //打印鏈表


    swipList( &head, 2, 4);
    printf("交換3,5位置之後的鏈表:\n");//因爲傳進去的是不帶表頭的數據
    printList(head); //打印鏈表


    //FastSort(&head, 1, sizeList(head) - 1);

    fastsort(&head,p->next);

    printf("快速排序:\n");
    printList(head);

    clearList(h);

   system("pause");
   return 0;
}

這裏寫圖片描述

參考於:http://blog.csdn.net/liuduoqing/article/details/2278492
http://www.jb51.net/article/37300.htm

發佈了46 篇原創文章 · 獲贊 25 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章