1. 程式人生 > >單鏈表C語言操作

單鏈表C語言操作

    連結串列是一種相對於順序儲存空間而言的鏈式儲存結構,是一種在儲存空間而言不連續的一種資料結構。其中的每個元素稱為節點,包含有資料域和指標域,指標域儲存的是指向下一個節點,資料域代表這個元素的資料

struct ListNode 
{ 
    int data; 
    struct ListNode *next; 
};

頭節點,存放第一個節點的地址,資料域一般設為0,最後一個節點的指標域一般設為NULL,沒有後繼節點。

  • 建立一個單鏈表,先建立一個頭節點,然後用一個臨時節點去初始化連結串列中的元素
pNode CreateListnew()
{
	int len;//連結串列長度
	int val;//節點的數值
	int i=0;
	//建立連結串列的頭部 頭節點不存放資料,指標指向第一個節點
	pNode pHead=(pNode)malloc(sizeof(Node));//分配空間
	if(pHead==NULL)
	{
		printf("malloc fail for header\r\n");
		return NULL;
	}
    pHead->next=NULL;//頭節點指標域清空
	pNode tmp=pHead;//臨時節點 初始是頭節點

	for(i=0;i<Length;i++)
	{
		pNode pNew=(pNode)malloc(sizeof(Node));//分配空間
		if(pNew==NULL)
		{
			printf("malloc fail for new node\r\n");
			return NULL;
		}
		pNew->data=2*i;//新節點的資料域
		tmp->next=pNew;//將pNew指向新節點插入連結串列
		tmp=pNew;//將新節點賦給這個臨時節點,方便下一次插入
	}
	tmp->next=NULL;//最後節點的指標域清空
	printf("create list success\r\n");
	return pHead;  //f返回頭節點
}

 

  • 單鏈表求長

設定當前指標P和一個計數器i,初始時P指向連結串列中的第一個結點,p每向下移動一個結點時,i就加1,直到到達p連結串列的尾部

//測試連結串列長度
int ListLength(pNode List)
{
    pNode P=List->next;//傳參的是頭節點,開始P應該是指向第一個節點
    int i=0;
    while(P!=NULL)
    {
        i++;
        P=P->next;
    }
    return i;
}

 

  • 遍歷連結串列

和單鏈表求長類似

//遍歷
void TraverseList(pNode List)
{
    pNode P=List->next;
    printf("遍歷連結串列值為:\r\n");
    if(P==NULL)
    {
        printf("list is null!\r\n");
    }
    while(P!=NULL)
    {
        printf("%d ",P->data);
        P=P->next;
    }
    printf("\r\n");
}

 

  • 連結串列的尾插

找到整個連結串列的尾節點,建立一個新節點,是這個節點指向尾節點的next,並將這個新節點的指標域設定成空。

void tail_insert(pNode List,int val)
{
    pNode P=List;

    while(P->next!=NULL)
    {
        P=P->next;
    }
     pNode Tmp=(pNode)malloc(sizeof(Node));
    if(Tmp==NULL)
    {
        printf("malloc fail for Tmp");
        return -1;
    }
    P->next=Tmp;
    Tmp->data=val;
    Tmp->next=NULL;
}

 

  • 單鏈表的頭插

有新的結點就把此結點放在頭結點的後面。操作過程中只需要把頭節點的指標域賦給建立的新節點的指標域,也就是新節點的後繼是原來的第一個節點,然後讓新結點變為連結串列的第一個節點

void HeadInsert(pNode List,int val)
{
  pNode P=List;//頭節點
  pNode Tmp=(pNode)malloc(sizeof(Node));
    if(Tmp==NULL)
    {
        printf("malloc fail for Tmp");
        return ;
    }
  Tmp->next=P->next;//頭節點的指標域賦給建立的節點的指標域
  Tmp->data=val;
  P->next=Tmp; // 讓新結點變為連結串列的第一個節點

}

 

  • 連結串列中間插入

首先根據輸入連結串列的插入索引獲取要插入節點的前一個節點,建立一個新節點,前一個節點的指標域賦給這個新節點的指標域,並讓前一個節點的指標域指向這個新建立的節點。

void InsertList(pNode List,int pos,int val)
{
    pNode P=List;
    int position=0;
    //尋找pos節點的前驅節點
    while(P!=NULL&&position<pos-1)
    {
        P=P->next;
        position++;
    }
    pNode Tmp=(pNode)malloc(sizeof(Node));
    if(Tmp==NULL)
    {
        printf("malloc fail for Tmp");
        return ;
    }
    //insert node
    Tmp->data=val;
    Tmp->next=P->next;
    P->next=Tmp;
}

 

  • 單鏈表的刪除

首先根據輸入連結串列的刪除索引獲取要刪除節點的前一個節點,建立一個新節點,前一個節點的指標域賦給這個新節點,並讓新建立的節點的指標域指向前一個節點的指標域。

void DeleteList(pNode List,int pos)
{
    int position=0;
    pNode P=List;
    //尋找pos節點的前驅節點
    while(P!=NULL&&position<pos-1)
    {
        P=P->next;
        position++;
    }
    pNode Tmp=P->next;
    P->next=Tmp->next;
    free(Tmp);
    Tmp=NULL;
}

 

下面是一個綜合例子,使用頭插法建立一個連結串列,開始時建立了10個元素,然後可以使用上面的一些單鏈表的函式對這個連結串列進行插入,刪除和遍歷

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

#define Length 10

 struct ListNode
{
	int data;
	struct ListNode *next;
};
typedef struct ListNode Node;
typedef struct ListNode* pNode;
//typedef Node* pNode;

//連結串列初始化
void ListInit(pNode List)
{
    List=(pNode)malloc(sizeof(Node));//分配空間
    if(List==NULL)
    {
        printf("malloc fail\r\n");
        return;
    }
    List->next=NULL;
}

//建立單鏈表
pNode CreateList()
{
	int len;//連結串列長度
	int val;//節點的數值
	int i=0;
	//建立連結串列的頭部 頭節點不存放資料,指標指向第一個節點
	pNode pHead=(pNode)malloc(sizeof(Node));//分配空間
	if(pHead==NULL)
	{
		printf("malloc fail for header\r\n");
		return NULL;
	}
	//建立連結串列的尾部 初始指向頭部 並將指標域置位空
	pNode pTail=pHead;
	pTail->next=NULL;
	for(i=0;i<Length;i++)
	{
		pNode pNew=(pNode)malloc(sizeof(Node));//分配空間
		if(pNew==NULL)
		{
			printf("malloc fail for new node\r\n");
			return NULL;
		}
		pNew->data=2*i;
		pTail->next=pNew; //末尾節點指標指向下一個新資料
		pNew->next=NULL;
		pTail=pNew; //將新節點複製給末尾節點
	}
	printf("create list success\r\n");
	return pHead;
}
//建立單鏈表
pNode CreateListnew()
{
	int len;//連結串列長度
	int val;//節點的數值
	int i=0;
	//建立連結串列的頭部 頭節點不存放資料,指標指向第一個節點
	pNode pHead=(pNode)malloc(sizeof(Node));//分配空間
	if(pHead==NULL)
	{
		printf("malloc fail for header\r\n");
		return NULL;
	}
    pHead->next=NULL;//頭節點指標域清空
	pNode tmp=pHead;

	for(i=0;i<Length;i++)
	{
		pNode pNew=(pNode)malloc(sizeof(Node));//分配空間
		if(pNew==NULL)
		{
			printf("malloc fail for new node\r\n");
			return NULL;
		}
		pNew->data=2*i;
		tmp->next=pNew;//將pNew指向新節點插入連結串列
		//pTail->next=pNew; //末尾節點指標指向下一個新資料
		//pNew->next=NULL;
		//pTail=pNew; //將新節點複製給末尾節點
		tmp=pNew;//將新節點賦給這個臨時節點,方便下一次插入
	}
	tmp->next=NULL;//最後節點的指標域清空
	printf("create list success\r\n");
	return pHead;
}
//測試連結串列長度
int ListLength(pNode List)
{
    pNode P=List->next;
    int i=0;
    while(P!=NULL)
    {
        i++;
        P=P->next;
    }
    return i;
}

//遍歷
void TraverseList(pNode List)
{
    pNode P=List->next;
    printf("遍歷連結串列值為:\r\n");
    if(P==NULL)
    {
        printf("list is null!\r\n");
    }
    while(P!=NULL)
    {
        printf("%d ",P->data);
        P=P->next;
    }
    printf("\r\n");
}
//查詢
pNode FindList(pNode List)
{
    pNode P=List->next;
    int num=0;
    int val=0;
    printf("input your val");
    scanf("%d",&val);
    while((P!=NULL)&&(P->data)!=val)
    {
        P=P->next;
        num++;
    }
    if(P!=NULL)
        printf("找到節點:%d",num+1);
    else
        printf("找不到對應的節點");
    printf("\r\n");
    return P;
}
void InsertList(pNode List,int pos,int val)
{
    pNode P=List;
    int position=0;
    //尋找pos節點的前驅節點
    while(P!=NULL&&position<pos-1)
    {
        P=P->next;
        position++;
    }
    pNode Tmp=(pNode)malloc(sizeof(Node));
    if(Tmp==NULL)
    {
        printf("malloc fail for Tmp");
        return ;
    }
    //insert node
    Tmp->data=val;
    Tmp->next=P->next;
    P->next=Tmp;

}
//頭插  有新的結點就把此結點放在頭結點的後面
void HeadInsert(pNode List,int val)
{
  pNode P=List;//頭節點
  pNode Tmp=(pNode)malloc(sizeof(Node));
    if(Tmp==NULL)
    {
        printf("malloc fail for Tmp");
        return ;
    }
  Tmp->next=P->next;//頭節點的指標域賦給建立的節點的指標域
  Tmp->data=val;
  P->next=Tmp; // 讓新結點變為連結串列的第一個節點

}
void tail_insert(pNode List,int val)
{
    pNode P=List;

    while(P->next!=NULL)
    { // 讓新結點變為連結串列的第一個節點
        P=P->next;
    }
     pNode Tmp=(pNode)malloc(sizeof(Node));
    if(Tmp==NULL)
    {
        printf("malloc fail for Tmp");
        return ;
    }
    P->next=Tmp;
    Tmp->data=val;
    Tmp->next=NULL;
}
void DeleteList(pNode List,int pos)
{
    int position=0;
    pNode P=List;
    //尋找pos節點的前驅節點
    while(P!=NULL&&position<pos-1)
    {
        P=P->next;
        position++;
    }
    pNode Tmp=P->next;
    P->next=Tmp->next;
    free(Tmp);
    Tmp=NULL;
}

int main()
{
		//pNode List=CreateList();
		pNode List=CreateListnew();//建立10個元素的節點並返回頭節點
		TraverseList(List);
		printf("List Length:%d\r\n",ListLength(List));
		//FindList(List);
		InsertList(List,3,50);//指定位置插入
		TraverseList(List);//遍歷
		printf("List Length:%d\r\n",ListLength(List));
		DeleteList(List,3);//刪除元素
          TraverseList(List);//遍歷
          tail_insert(List,999);//尾插
          TraverseList(List);//遍歷
          HeadInsert(List,11);//頭插
          TraverseList(List);//遍歷
          printf("List Length:%d\r\n",ListLength(List));
		return 0;
}