程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 對鏈表的相關操作及數據結構的再理解

對鏈表的相關操作及數據結構的再理解

編輯:關於C語言

結點的操作           由於鏈表是n個離散結點彼此通過指針相連,所以對鏈表的相關操作主要通過頭指針(存放了頭結點的地址)對結點進行操作來實現。          1.如何將q所指向的結點插入到p所指向結點的後面?                   有兩個方法                       第一種: 采用臨時變量                           r=p->pNext;//用r保存p所指向結點的下一個結點地址                           p->pNext=q;//此時p的指針域指向q所指的結點的地址                          q->pNext=r;                        第二種:不采用臨時變量                             q-pNext=p->pNext;//讓p和q所指向結點的指針域指向後面的同一個結點                             p-pNext=q;//再讓p的指針域指向q結點              2.如何刪除一個節點(思路:用一個臨時變量r來保存要刪除的結點,再刪除p後面的那個結點)                             r=p->pNext;                               p->pNext=p->pNext->pNext;                                        free(r);                             r=NULL;                                            3.如何判斷鏈表是否為空(思路:空鏈表只有一個頭結點,所以只需讓頭結點的指針域為NULL即可)         對鏈表的相關操作     實例說明:   

#include<stdio.h>   
#include<malloc.h>   
#include<stdlib.h>   
typedef struct Node  
{  
    int data;//數據域   
    struct Node *pNext;//指針域   
}NODE,*PNODE;  
PNODE CreateList();//創建鏈表   
void TraverseList(PNODE);//遍歷鏈表   
bool IsEmpty(PNODE);//判斷鏈表是否為空   
int Length(PNODE);//求鏈表長度   
bool InsertNode(PNODE,int,int);//插入結點   
bool DeleteNode(PNODE,int,int *);//刪除結點   
bool QueryNode(PNODE,int);//查找結點    
bool ModifyNode(PNODE,int,int);//修改結點   
void SortList(PNODE);//排序   
  
int main()  
{  
    PNODE pHead=NULL;  
    pHead=CreateList();//將創建鏈表的頭指針的地址賦給pHead   
    if(0==Length(pHead))  
    {  
        printf("鏈表無有效節點,退出程序!\n");  
        exit(-1);  
    }  
    TraverseList(pHead);  
    if(InsertNode(pHead,2,100))  
    {  
        printf("插入後");  
        TraverseList(pHead);   
    }  
    else  
    {  
        printf("插入操作失敗!\n");  
    }  
    SortList(pHead);  
    printf("排序後");  
    TraverseList(pHead);  
  
    return 0;  
}  
PNODE CreateList()  
{  
    int len;//用來保存需要創建鏈表的結點個數   
    int i;  
    int val;//用來臨時存放新節點的值   
    PNODE pHead=(PNODE)malloc(sizeof(NODE));//動態分配一塊內存,該內存保存頭結點的地址,並將其賦給pHead   
    PNODE pTail=pHead;  
    PNODE pNew;  
    pTail->pNext=NULL;//將尾結點的指針域賦為NULL   
    if(NULL==pHead)  
    {  
        printf("分配失敗,程序終止運行!\n");  
        exit(-1);  
    }  
    printf("請輸入你要創建鏈表的結點個數:len=");  
    scanf("%d",&len);  
    for(i=0;i<len;i++)  
    {  
        printf("請輸入第%d個結點的值:",i+1);  
        scanf("%d",&val);  
        pNew=(PNODE)malloc(sizeof(NODE));//創建新臨時結點   
        if(NULL==pNew)  
        {  
            printf("分配失敗,程序終止運行!\n");  
            exit(-1);  
        }  
        pNew->data=val;  
        pTail->pNext=pNew;//將新結點掛到原尾結點的後面   
        pNew->pNext=NULL;//將新結點的指針域賦為NULL   
        pTail=pNew;//將新結點置為尾結點   
    }  
    return pHead;  
}  
void TraverseList(PNODE pHead)  
{  
    PNODE p=pHead->pNext;//將頭結點的指針域指向首結點(鏈表的第一個有效結點),並賦給指針變量p,此時p指向首節點的地址   
    printf("遍歷整個鏈表:");  
    while(NULL!=p)//當p指向首節點的地址不為NULL(即鏈表不為空),循環輸入個結點的值   
    {  
        //當p指向尾結點的地址時,可輸出尾結點的值   
        //但此時尾結點指針域為NULL,將跳出while循環   
        printf("%d  ",p->data);  
        p=p->pNext;//將p指向下一個結點的地址賦給p指針   
    }  
    printf("\n");   
}  
bool IsEmpty(PNODE pHead)  
{  
    if(NULL==pHead->pNext)  
        return true;  
    else  
        return false;  
}  
int Length(PNODE pHead)  
{  
    PNODE p=pHead->pNext;//此時p指向鏈表的首結點(第一個有效結點)的地址   
    int len=0;  
    while(NULL!=p)  
    {  
        ++len;  
        p=p->pNext;  
    }  
    return len;  
}  
bool InsertNode(PNODE pHead,int pos,int val)  
{  
    int i=0;  
    PNODE p=pHead,q;  
    PNODE pNew;  
    while(NULL!=p&&i<pos-1)//目的是為了使p指向要插入位置的前一個結點   
    {  
        p=p->pNext;  
        ++i;//如鏈表只有兩個有效結點,要插入的位置結點pos=3,i=2時,2<3-1不成立,循環結束,   
    }  
    if(i>pos-1||NULL==p)//p為NULL說明要插入位置結點的前一個結點不存在,i>pos-1是為了防止用戶輸入pos為像0、-1等非法數據   
        return false;  
    pNew=(PNODE)malloc(sizeof(NODE));//為新節點分配內存   
    if(NULL==pNew)  
    {  
        printf("動態內存分配失敗,程序終止!\n");  
        exit(-1);  
    }  
    pNew->data=val;  
    q=p->pNext;  
    p->pNext=pNew;  
    pNew->pNext=q;  
    return true;   
}  
bool DeleteNode(PNODE pHead,int pos,int *pVal)  
{  
    int i=0;  
    PNODE p=pHead,q;  
    while(NULL!=p->pNext&&i<pos-1)  
    {  
        p=p->pNext;  
        ++i;  
    }  
    if(i>pos-1||NULL==p)  
        return false;  
    q=p->pNext;  
    *pVal=q->data;  
    p->pNext=p->pNext->pNext;  
    free(q);  
    q=NULL;  
    return true;  
}  
void SortList(PNODE pHead)  
{  
    int i,j,t;  
    int len=Length(pHead);//用len來保存鏈表的長度   
    PNODE p,q;  
    for(i=0,p=pHead->pNext;i<len-1;p=p->pNext,i++)//比較趟數   
    {  
        for(j=i+1,q=p->pNext;j<len;q=q->pNext,j++)//比較對數   
        {  
            if(p->data>q->data)  
            {  
                t=p->data;  
                p->data=q->data;  
                q->data=t;  
            }  
        }  
    }  
}  
bool QueryNode(PNODE pHead,int pos)  
{  
    int i=0;  
    PNODE p=pHead,q;  
    while(NULL!=p->pNext&&i<pos-1)  
    {  
        p=p->pNext;  
        ++i;  
    }  
    if(i>pos-1||NULL==p)  
        return false;     
    q=p->pNext;  
    printf("第%d號位置上結點的值為:%d\n",pos,q->data);  
    return true;  
}  
bool ModifyNode(PNODE pHead,int pos,int val)  
{  
    int i=0;  
    PNODE p=pHead,q;  
    while(NULL!=p->pNext&&i<pos-1)  
    {  
        p=p->pNext;  
        ++i;  
    }  
    if(i>pos-1||NULL==p)  
        return false;     
     q=p->pNext;  
     q->data=val;  
     printf("修改第%d號位置上結點的值為:%d\n",pos,q->data);  
     return true;  
}  

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
typedef struct Node
{
int data;//數據域
struct Node *pNext;//指針域
}NODE,*PNODE;
PNODE CreateList();//創建鏈表
void TraverseList(PNODE);//遍歷鏈表
bool IsEmpty(PNODE);//判斷鏈表是否為空
int Length(PNODE);//求鏈表長度
bool InsertNode(PNODE,int,int);//插入結點
bool DeleteNode(PNODE,int,int *);//刪除結點
bool QueryNode(PNODE,int);//查找結點 
bool ModifyNode(PNODE,int,int);//修改結點
void SortList(PNODE);//排序

int main()
{
PNODE pHead=NULL;
pHead=CreateList();//將創建鏈表的頭指針的地址賦給pHead
if(0==Length(pHead))
{
printf("鏈表無有效節點,退出程序!\n");
exit(-1);
}
TraverseList(pHead);
if(InsertNode(pHead,2,100))
{
printf("插入後");
        TraverseList(pHead); 
}
else
{
printf("插入操作失敗!\n");
}
SortList(pHead);
printf("排序後");
TraverseList(pHead);

return 0;
}
PNODE CreateList()
{
int len;//用來保存需要創建鏈表的結點個數
int i;
int val;//用來臨時存放新節點的值
PNODE pHead=(PNODE)malloc(sizeof(NODE));//動態分配一塊內存,該內存保存頭結點的地址,並將其賦給pHead
PNODE pTail=pHead;
PNODE pNew;
    pTail->pNext=NULL;//將尾結點的指針域賦為NULL
if(NULL==pHead)
{
printf("分配失敗,程序終止運行!\n");
exit(-1);
}
printf("請輸入你要創建鏈表的結點個數:len=");
scanf("%d",&len);
for(i=0;i<len;i++)
{
printf("請輸入第%d個結點的值:",i+1);
scanf("%d",&val);
pNew=(PNODE)malloc(sizeof(NODE));//創建新臨時結點
        if(NULL==pNew)
{
printf("分配失敗,程序終止運行!\n");
exit(-1);
}
pNew->data=val;
pTail->pNext=pNew;//將新結點掛到原尾結點的後面
        pNew->pNext=NULL;//將新結點的指針域賦為NULL
pTail=pNew;//將新結點置為尾結點
}
return pHead;
}
void TraverseList(PNODE pHead)
{
PNODE p=pHead->pNext;//將頭結點的指針域指向首結點(鏈表的第一個有效結點),並賦給指針變量p,此時p指向首節點的地址
printf("遍歷整個鏈表:");
while(NULL!=p)//當p指向首節點的地址不為NULL(即鏈表不為空),循環輸入個結點的值
{
//當p指向尾結點的地址時,可輸出尾結點的值
//但此時尾結點指針域為NULL,將跳出while循環
printf("%d  ",p->data);
p=p->pNext;//將p指向下一個結點的地址賦給p指針
}
printf("\n"); 
}
bool IsEmpty(PNODE pHead)
{
if(NULL==pHead->pNext)
return true;
else
return false;
}
int Length(PNODE pHead)
{
PNODE p=pHead->pNext;//此時p指向鏈表的首結點(第一個有效結點)的地址
int len=0;
while(NULL!=p)
{
++len;
p=p->pNext;
}
    return len;
}
bool InsertNode(PNODE pHead,int pos,int val)
{
int i=0;
PNODE p=pHead,q;
    PNODE pNew;
while(NULL!=p&&i<pos-1)//目的是為了使p指向要插入位置的前一個結點
{
p=p->pNext;
++i;//如鏈表只有兩個有效結點,要插入的位置結點pos=3,i=2時,2<3-1不成立,循環結束,
}
if(i>pos-1||NULL==p)//p為NULL說明要插入位置結點的前一個結點不存在,i>pos-1是為了防止用戶輸入pos為像0、-1等非法數據
return false;
    pNew=(PNODE)malloc(sizeof(NODE));//為新節點分配內存
if(NULL==pNew)
{
printf("動態內存分配失敗,程序終止!\n");
exit(-1);
}
    pNew->data=val;
q=p->pNext;
p->pNext=pNew;
    pNew->pNext=q;
    return true; 
}
bool DeleteNode(PNODE pHead,int pos,int *pVal)
{
int i=0;
PNODE p=pHead,q;
while(NULL!=p->pNext&&i<pos-1)
{
p=p->pNext;
++i;
}
if(i>pos-1||NULL==p)
return false;
q=p->pNext;
*pVal=q->data;
p->pNext=p->pNext->pNext;
free(q);
q=NULL;
return true;
}
void SortList(PNODE pHead)
{
int i,j,t;
int len=Length(pHead);//用len來保存鏈表的長度
PNODE p,q;
    for(i=0,p=pHead->pNext;i<len-1;p=p->pNext,i++)//比較趟數
{
for(j=i+1,q=p->pNext;j<len;q=q->pNext,j++)//比較對數
{
if(p->data>q->data)
{
t=p->data;
p->data=q->data;
q->data=t;
}
}
}
}
bool QueryNode(PNODE pHead,int pos)
{
int i=0;
PNODE p=pHead,q;
while(NULL!=p->pNext&&i<pos-1)
{
p=p->pNext;
++i;
}
if(i>pos-1||NULL==p)
return false; 
q=p->pNext;
printf("第%d號位置上結點的值為:%d\n",pos,q->data);
return true;
}
bool ModifyNode(PNODE pHead,int pos,int val)
{
int i=0;
PNODE p=pHead,q;
while(NULL!=p->pNext&&i<pos-1)
{
p=p->pNext;
++i;
}
if(i>pos-1||NULL==p)
return false; 
     q=p->pNext;
q->data=val;
printf("修改第%d號位置上結點的值為:%d\n",pos,q->data);
return true;
}

 

注意:            1.在vc++中,c編譯器不支持bool函數,但c++編譯器支持,所以這裡我用的是c++編譯器。             2.c編譯過程中常見錯誤:illegal use of this type as an expression 是由於c語言不允許臨時定義變量,所有定義的變量都必須放在函數開頭,這也是c和c++的重要區別       數據結構的再理解           狹義上的理解:數據結構是專門研究數據存儲(包括個體的存儲和個體關系的存儲)問題。           廣義上的理解:數據結構既包含數據的存儲也包含數據的操作。算法是對存儲數據的操作。   算法:          狹義上的理解:算法和數據的存儲方式密切相關          廣義上的理解:算法和數據的存儲方式無關(這就是泛型的思想)   泛型:利用某種技術達到的效果就是不同的存儲方式,執行的操作是一樣的。泛型主要通過模板,運算符的重載,指針來實現,在c++中經常用到。       補充          線性結構:                   連續存儲【數組】                            優點:存取速度快                            缺點:插入刪除元素很慢,空間通常是有限制的,事先必須知道數組的長度,而且需要大塊連續內存塊                     離散存儲【鏈表】                            優點:插入刪除元素很快,空間沒有限制的;                            缺點: 存取速度很慢  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved