C語言鏈式存儲之靜態鏈表

目錄

1.什麼是靜態鏈表

2.添加一個新元素

3.插入結點

4.刪除結點

5.靜態鏈表的初始化

6.打印靜態鏈表

7. 查找給定結點的上一個結點的下標

8.主函數


1.什麼是靜態鏈表

   用數組來代替指針,描述單鏈表。定義一個結構體,結構體中包含兩個整形變量,第一個整形變量等價於鏈表中的data域,第二個整形元素等價於單鏈表中的next指針域,這個變量用cur表示,用來存儲下一個元素的數組下標。結構體類型如下:

struct node{
	int data;       //數據域
	int cur;        //指針域
}slist[M],snode; 

注意:<1>靜態鏈表中對數組中的第一個元素和最後一個元素做特殊處理,第一個元素相當於單鏈表中的尾指針,數據域不存數據,cur域用來存儲備用鏈表中的第一個元素的下標;最後一個元素中的data域同樣不存數據,cur域用來存儲第一個放數據的元素的下標,該結點相當於單鏈表中的頭結點(注意不是首結點);

           <2>備用鏈表:未被使用的數組元素被稱爲備用鏈表;

2.添加一個新元素

node* createnode(node* p,int e)
{
	int a,l;
	l = 0;
	if(p[M-1].cur==0)        //表示當前鏈表爲空
	{
	   a = 1;
	   p[a].data = e;        //將數據放到下標爲1的結點中
	   p[0].cur =  p[a].cur; //改變第一個結點中所存儲的備用鏈表的第一個節點的下標 
	   p[a].cur = 0;         //將尾結點指向空 
	   p[M-1].cur = 1;       //將頭結點中的下標指向首結點 
	} 
	else
	{
		a = p[0].cur;         //找到備用鏈表中第一個結點的下標 
		p[0].cur = p[a].cur;  //備用鏈表中的下一個元素的下標 
		l = findcur(p,0);     //找到鏈表中cur域爲0的結點的下標 
		p[l].cur = a;         //將之前的尾結點指向新插入的結點(即將之前尾結點的cur域賦值爲新結點的下標值) 
		p[a].data = e;        //完成對新結點數據域的賦值 
		p[a].cur  = 0;	      //使其指向空 
	}
	return p;
}

3.插入結點​​​​​​​

  (這裏和書上實現不太一樣)

要點:<1>首先獲取備用鏈表中的第一個空閒結點,作爲這個插入元素的存儲結點,將數據存到這個節點的數據域中;

           <2>獲取第i個元素之前的結點的下標,讓這個結點指向插入結點(即將插入結點的下標賦值給i之前結點的cur域);

           <3>將這個新插入結點的cur賦值爲i元素的下標,即完成新插入結點的指向。

//在第i個元素之前插入元素e
node* insertnode(node* p,int i,int e)
{
	int l,j;
	//如果當前表是空的直接退出 
    if(p[M-1].cur==0)
	{
		printf("鏈表爲空,不能插入!\n");
		return p; 
	} 
	if(i<1||i>(M-1))
	{
		printf("要插入的結點不在鏈表範圍內,不能插入\n");
		return p;
	}
	l = p[0].cur;             //先找到備用鏈表中第一個空閒結點
	if(l)                     //表示鏈表沒有滿,可以取到空閒結點 
	{
		p[0].cur = p[l].cur;  //將備用鏈表的首結點 放在第一個鏈表的cur中 
		j = findcur(p,i);     //找到下標爲i的那個結點的前一個節點的下標 
		p[j].cur = l;         //將前一個結點指向這個新結點   
		p[l].data = e;
		p[l].cur = i;		  //插入的這個結點指向i結點1 
	}
	return p;
}

 

4.刪除結點

要點:<1>查找要刪除結點的上一個結點,使該結點的遊標(cur)指向要刪除結點的下一個結點

           <2>回收刪除的結點,將該回收結點放到備用鏈表頭:第一,將第一個結點的遊標賦值給回收結點的遊標;第二,將第一                  個結點的遊標指向回收結點。

//刪除鏈表中第l個結點
node* deletenode(node* p,int l)
{
	if(p[M-1].cur == 0)        //頭指針指向空,則鏈表爲空不能刪除 
	{
		printf("the list is null\n");
		return p;
	}
	if((l<1)||(l>=(M-2)))          //如果輸入的位置在第一個和最後一個結點之外,也不能刪除,輸入範圍不對 
	{
		printf("the location is error!\n");
		return p;
	}
	int temp;
	int c;
	c = findcur(p,l);         //找到上一個指向要輸入的這個結點的下標 
	p[c].cur = p[l].cur;      //將要刪除結點的上一個結點的cur指向要刪除結點的下一個結點 
   	p[l].cur=p[0].cur ;       //將刪除了的這個空閒結點的遊標指向0中存的遊標 ,實現將該結點會收到備用鏈表中 
	p[0].cur = l;            //將0中存的第一個備用鏈表的遊標指向剛剛刪除的這個結點 
	return p;	
} 

 

5.靜態鏈表的初始化

目標:將鏈表初始化爲備用鏈表

要點:1. 從第一個結點開始,使其cur指向下一個結點(即備用鏈表的首結點爲1,後面的結點依次連接起來);

           2. 最後一個元素的cur域置爲0,表示該鏈表爲空鏈表;

//初始化所要做的操作就是將所有的cur都置爲下一個元素的數組下標,尤其是最後一個元素的下標置爲0,表示該鏈表爲空
node* initlist(node* p)
{
	int i;
	for(i=0;i<M-1;i++)
	{
		p[i].cur =(i+1);
	}
	p[M-1].cur = 0;                       //表示當前鏈表爲空
	return p; 
} 

6.打印靜態鏈表

int plist(node* p)
{
	int m = p[M-1].cur;               //從首結點開始打印
	while(m!=0)
	{
		printf("%d,%d\n",m,p[m].data);
		m = p[m].cur;
	}
	return 0;
}

7. 查找給定結點的上一個結點的下標

int findcur(node* p,int c)
{
	int i=1;
	int l=(M-1);
	while(c==0)
	{
		if(p[i].cur == 0)
		{
			return i;
		}
		else
		{
			i = p[i].cur;
		}
	}
	for(i=1;i<c;i++)    //找到i元素的上一個結點的下標 
	{
         l=p[l].cur;
	}
	return l;
}

8.主函數

#include "stdio.h"
#include "stdlib.h"
#define M 1000 
struct node{
	int data;
	int cur;
}slist[M],snode; 
int main()
{
	node *p;
	int n,i=0,e;	
	p = &slist[0];
	p = initlist(p);
	scanf("%d",&n);
	while(n!=i)
	{
		scanf("%d",&e);
		createnode(p,e);
		i++;
	}
	p = insertnode(p,2,13);
	plist(p);
	p = deletenode(p,5);
	plist(p);
	return 0;
}

 

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