c提高5-链表

版权声明:本文为博主原创文章,转前请跟博主吱一声。 https://blog.csdn.net/Ga4ra/article/details/89785898

链表

关键字:非连续存储,动态生成,指针连接,数据与和指针域。

分类

按头节点:

  • 带头链表(头节点无数据域)
  • 不带头链表

按节点组织形式:

  • 单向链表
  • 双向链表
  • 循环链表

按存储结构:

  • 静态链表,用数组实现或栈中分配内存,连续存储,容量固定。
  • 动态链表,用malloc()等内存申请函数实现。

编程元素

pHead,pCurrent,pPrev,pNext.,还有新建节点pMalloc.

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


typedef struct node{
    int data;
	struct node *next;
}linklist;


linklist *Creatlist();
linklist *Find(linklist *head,int x);
int add_to_end(linklist *p,int data);
int insert(linklist *head,int originData,int data);
int delNode(linklist *head,int data);
void linklist_output(linklist *head);
int inverse(linklist *head);
int linklist_destroy(linklist **head);


int main(void)
{
	int data;
	linklist *pHead = NULL;
	int ret;
	pHead = Creatlist();
	if(pHead == NULL){
		printf("CreatList() err\n");
		return 1;
	} 
	linklist_output(pHead);
	
	
	ret = insert(pHead,2,5);
	if(ret != 0)
	{
		return 0;
	}
	linklist_output(pHead);
	
	ret = inverse(pHead);
	if(ret != 0)
	{
		return 0;
	}
	linklist_output(pHead);
	
	ret = linklist_destroy(&pHead);
	if(ret != 0)
	{
		return 0;
	}
	return 0;
}


//initial the linklist  
linklist *Creatlist()
{
	/*
	    with a head node;
		single direction;
	    loop creation;
	    input ends with -1.
		return the address of the head node. 
	*/
	int data;
	linklist *pHead = NULL,*pMalloc = NULL,*pCurrent = NULL;
	
	pHead=(linklist*)malloc(sizeof(linklist));
	if(pHead == NULL)
	{
		return NULL;
	} 
	pHead->data = 0;
	pHead->next = NULL;
	
	pCurrent = pHead;
	
	
	while(data != -1)
	{
		pMalloc = (linklist*)malloc(sizeof(linklist));
		if(pMalloc == NULL)
		{
			linklist_destroy(&pHead); 
			return pHead;
		} 
		
		printf("input data(linklist ends with -1):");
		scanf("%d",&data);
		fflush(stdin);
		
		pMalloc->data = data;
		pMalloc->next = NULL;
		
		pCurrent->next=pMalloc;
		pCurrent=pMalloc;
	}
	pCurrent->next=NULL;
	return pHead;
}

void linklist_output(linklist *head)
{
	linklist *pCurrent = NULL;
	if(head == NULL)
	{
		printf("linklist_output() arg can't be NULL.\n");
		return ;
	}
	pCurrent = head->next;
	while(pCurrent)
	{
		printf("%d ",pCurrent->data);	
		pCurrent = pCurrent->next;
	}
	printf("\n");
	
}


int add_to_end(linklist *head,int data)
{
	linklist *pMalloc = NULL,*pRear = NULL;
	pMalloc = (linklist*)malloc(sizeof(linklist));
	if(pMalloc == NULL)
	{
		printf("InsertAfter() : malloc() error.\n");
		return -1;
	}
	pMalloc->data = data;
	pMalloc->next = NULL;
	pRear = head;
	while(pRear->next != NULL){
		pRear = pRear->next;
	}
	pRear->next = pMalloc;
	return 0;
}

int insert(linklist*head,int originData,int data)
{
	linklist *pPre = NULL,*pCurrent = NULL,*pMalloc = NULL; 
	
	if(head == NULL)
	{
		printf("insert() arg linklist*head can't be NULL.\n");
		return -1;
	}
	
	pPre = head;
	pCurrent = head->next;
	
	pMalloc = (linklist*)malloc(sizeof(linklist));
	if(pMalloc == NULL)
	{
		printf("InsertAfter() : malloc() error.\n");
		return -1;
	}
	pMalloc->data = data;
	pMalloc->next = NULL;
	
	/*
		if originData is found,pMalloc will replace it,
		or pMalloc will be added to the end.
	*/
	
	while(pCurrent)
	{
		if(pCurrent->data == originData)
		{
			break;
		}
		pPre = pCurrent;
		pCurrent = pCurrent->next;
	}
	
	
	
	pPre->next = pMalloc;
	pMalloc->next = pCurrent;
	
	return 0;
}

int delNode(linklist *head,int data_to_del)
{
	linklist *pPrev = NULL, *pCurrent = NULL;
	if(head == NULL)
	{
		printf("delNode() arg linklist*head can't be NULL.\n");
		return -1;
	}
	
	pPrev = head;
	pCurrent = head->next;
	
	while(pCurrent)
	{
		if(pCurrent->data == data_to_del)
		{
			break;
		}
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
	if(pCurrent == NULL)
	{
		printf("%d not found.\n",data_to_del);
		return -1;
	}
	pPrev->next = pCurrent->next;
	if(pCurrent != NULL)
	{
		free(pCurrent);
		pCurrent = NULL;
	}
	
	return 0;
}

int inverse(linklist *head){
	linklist *pPrev = NULL;
	linklist *pCurrent = NULL;
	linklist *pNext = NULL;
	
	if(head == NULL)
	{
		printf("delNode() arg linklist*head can't be NULL.\n");
		return -1;
	}
	
	if(head->next == NULL)
	{
		printf("the linklist has just one head node.\n");
		return -1;
	}
	
	pPrev = head;
	pCurrent = head->next;
	while(pCurrent){ 
		pNext = pCurrent->next;
		
		pCurrent->next = pPrev;
		
		pPrev = pCurrent;
		pCurrent = pNext;
		//pNext = pCurrent->next;  DON'T BE HERE锛?
	}
	
	/*
	  ---->O----->O------>NULL
			      pPrev    pCurrent/pNext
	*/
	head->next->next = NULL;
	head->next = pPrev;
	
	return 0;
}

int linklist_destroy(linklist **head)
{
	linklist *pHead,*pNext = NULL;
	if(head == NULL)
	{
		printf("linklist_destroy() arg linklist*head can't be NULL.\n");
		return -1;
	}
	pHead = *head;
	while(pHead)
	{
		pNext = pHead->next;
		pHead->next = NULL;
		free(pHead);
		pHead = pNext;
	}
	*head = NULL;
	return 0;
}

linux内核链表

上面的部分是传统链表,节点包含数据域和指针域。

Linus在28岁时发明了linux内核链表,让数据域包含指针域,进而实现不同结构体链接起来。

数据域不能包含万事万物,那就让万事万物包含链表节点。

这种链表需要手动实现计算成员偏移量。

//compute the offset of the member 
#define offsetof(TYPE,MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)

struct list_head{
    struct list_head *next,*prev;
}
struct Foo{
    int id;
    struct list_head list;
}
struct Bar{
    int id;
    struct list_head list;
}

int main()
{
    struct list_head head,*plist;
    struct Foo foo;
    struct Bar bar;
    
    INIT_LIST_HEAD(&head);
    
    list_add(&foo.list,head);
    list_add(&bar.list,head);
    
    list_for_each(plist,&head){
        struct Foo *node = list_entry(plist,struct Foo,list);
       	printf("%d \n",node->id);
    }
    
    return 0;
}

通用链表

基于linux内核链表,还可以做一点优化,让指针域地址和结构体地址重合。这种链表在实际中大量应用。

struct Foo{
    struct list_head list;
    int id;
}

可以把这种链表编译为动态库随时调用。

猜你喜欢

转载自blog.csdn.net/Ga4ra/article/details/89785898
今日推荐