【鏈表】帶頭結點的雙向循環鏈表

還需改進:

creat_node這個函數應有返回類型,來判斷新建結點是否成功,不然主函數中不管成不成功都會訪問該節點成員。

改了這個函數,在主函數中create_node後要判斷是否成功,不成功就提示並退出函數,退出前別忘了還要釋放鏈表!

同時create_link這個函數中也要判斷head是否申請成功,不成功的話同樣提示並退出函數。

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

struct dnode
{
    int num;

    struct dnode * prior;
    struct dnode * next;
};

typedef struct dnode Dnode;
typedef struct dnode * Dlink;

void create_dnode(Dlink *DblNode)
{
    int count = 10;

    do
    {
        *DblNode = (Dlink)malloc(sizeof(Dnode));
        count--;
    }while(!is_malloc_ok(*DblNode) && count);
}

int is_malloc_ok(Dlink DblNode)
{
    if(DblNode == NULL)
    {
        printf("malloc error!\n");
        return 0;
    }
    return 1;
}

void create_dlink(Dlink *DblHead)
{
    Dlink DblNode;
    create_dnode(&DblNode);

    *DblHead = DblNode;
    DblNode->next = DblNode;
    DblNode->prior= DblNode;
}

void insert_dnode_head(Dlink DblHead,Dlink DblNode)
{
    DblHead->next->prior = DblNode;
    DblNode->next = DblHead->next;
    DblHead->next = DblNode;
    DblNode->prior = DblHead;
}

void display(Dlink DblHead)
{
    if(DblHead == NULL)
    {
        printf("該鏈表已被釋放\n");
        return;
    }

    Dlink p = DblHead;
    
    printf("該鏈表顯示是:\n");
    if(p->next == DblHead)
    {
        printf("Link is empty!\n");
    }
    else
    {
        p = p->next;
        while(p != DblHead)
        {
            printf("num is %d\n",p->num);
            p = p->next;
        }
    }
}

int length(Dlink DblHead)
{
    Dlink p = DblHead->next;
    int count = 0;

    while(p != DblHead)
    {
        count++;
        p = p->next;
    }

    return count;
}

void insert_dnode_tail(Dlink DblHead,Dlink DblNode)
{
    DblNode->prior = DblHead->prior;
    DblHead->prior->next = DblNode;
    DblNode->next = DblHead;
    DblHead->prior = DblNode;
}

void insert_dnode_mid_before(Dlink DblHead,Dlink DblNode,int num)
{
    Dlink p = DblHead->next;

    while(p != DblHead && p->num != num)
    {
        p = p->next;
    }

    if(p == DblHead)
    {
        printf("No such node!\n");
    }
    else
    {
        DblNode->prior = p->prior;
        p->prior->next = DblNode;
        DblNode->next = p;
        p->prior = DblNode;
    }
}

void insert_dnode_mid_after(Dlink DblHead,Dlink DblNode,int num)
{
    Dlink p = DblHead->next;

    while(p != DblHead && p->num != num)
    {
        p = p->next;
    }

    if(p == DblHead)
    {
        printf("No such node!\n");
    }
    else
    {
        p->next->prior = DblNode;
        DblNode->next = p->next;
        p->next = DblNode;
        DblNode->prior = p;
    }
}

void delete_dnode(Dlink DblHead,int num)
{
    Dlink p = DblHead->next;

    while(p != DblHead && p->num != num)
    {
        p = p->next;
    }

    if(p == DblHead)
    {
        printf("No such node!\n");
    }
    else
    {
        p->next->prior = p->prior;
        p->prior->next = p->next;
        free(p);
    }
}

Dlink find(Dlink DblHead,int num)
{
    Dlink p = DblHead->next;

    while(p != DblHead && p->num != num)
    {
        p = p->next;
    }

    if(p == DblHead)
    {
        p = NULL;
        return p;
    }
    else
    {
        return p;
    }
}

void make_empty(Dlink DblHead)
{
    Dlink p = DblHead->next;
    Dlink q;

    while(p != DblHead)
    {
        q = p->next;
        p->next->prior = p->prior;
        p->prior->next = p->next;
        free(p);
        p = q;
    }
}

void release_dlink(Dlink *DblHead)
{
    make_empty(*DblHead);
    free(*DblHead);
    *DblHead = NULL;
}

int main()
{
    Dlink DblHead;
    Dlink DblNode;
    int i;
    int num;

    create_dlink(&DblHead);

    for(i = 0 ;i < 5; i++)
    {
        create_dnode(&DblNode);
        DblNode->num = i + 1;

        //insert_dnode_head(DblHead,DblNode);
        insert_dnode_tail(DblHead,DblNode);
    }

    display(DblHead);
    printf("該鏈表長度爲%d\n\n",length(DblHead));


    create_dnode(&DblNode);
    printf("請輸入你想插入的結點的數值:");
    scanf("%d",&DblNode->num);
    printf("請輸入你想在值爲哪個的結點前插入該結點:");
    scanf("%d",&num);

    insert_dnode_mid_before(DblHead,DblNode,num);

    display(DblHead);
    printf("該鏈表長度爲%d\n\n",length(DblHead));


    create_dnode(&DblNode);
    printf("請輸入你想插入的結點的數值:");
    scanf("%d",&DblNode->num);
    printf("請輸入你想在值爲哪個的結點後插入該結點:");
    scanf("%d",&num);

    insert_dnode_mid_after(DblHead,DblNode,num);

    display(DblHead);
    printf("該鏈表長度爲%d\n\n",length(DblHead));

    
    printf("請輸入你想刪除的結點的數值:");
    scanf("%d",&num);

    delete_dnode(DblHead,num);
    
    display(DblHead);
    printf("該鏈表長度爲%d\n\n",length(DblHead));

    
    printf("請輸入你想查找的結點的數值:");
    scanf("%d",&num);

    DblNode = find(DblHead,num);
    if(DblNode == NULL)
    {
        printf("沒有這個結點\n");
    }
    else
    {
        printf("這個結點的數值是%d\n\n",DblNode->num);
    }

    make_empty(DblHead);

    display(DblHead);
    printf("該鏈表長度爲%d\n\n",length(DblHead));

    release_dlink(&DblHead);
    display(DblHead);
    
    

    return 0;
}

小練:

要注意的點:

  1. 前指針和後指針名字
  2. MakeEmpty函數我清空的時候並沒有每刪一個都保持環,所以最後一步要讓head的prior指向head,不然再加node就會有錯
  3. Display函數要判斷一下頭結點是否爲空!空就是已經被釋放了!這個也要注意別忘了
  4. Delete函數裏也要注意刪除指針的時候,前後兩個節點有兩根線要連,不要只連一個了
#include <stdio.h>
#include <stdlib.h>

struct node
{
	int num;
	struct node *prior;
	struct node *next;
};

typedef struct node Node;
typedef struct node *Link;

int CreateNode(Link *new_node)
{
	*new_node = (Link)malloc(sizeof(Node));

	if(*new_node == NULL)
		return 0;
	return 1;
}

int CreateLink(Link *head)
{
	if(!CreateNode(head))
		return 0;

	(*head)->next = (*head);
	(*head)->prior = (*head);
	return 1;
}

void InsertHead(Link head, Link node)
{
	head->next->prior = node;
	node->next = head->next;
	head->next= node;
	node->prior = head;
}

void InsertTail(Link head, Link node)
{
	head->prior->next = node;
	node->prior = head->prior;
	head->prior = node;
	node->next = head;
}

void InsertBefore(Link head, Link node, int num)
{
	Link p = head->next;

	while(p != head)
	{
		if(p->num == num)
		{
			p->prior->next = node;
			node->prior = p->prior;
			node->next = p;
			p->prior = node;
			return;
		}
		p = p->next;
	}

	printf("Cannot find the node!\n");
}

void InsertAfter(Link head, Link node, int num)
{
	Link p = head->next;

	while(p != head)
	{
		if(p->num == num)
		{
			p->next->prior = node;
			node->next = p->next;
			p->next = node;
			node->prior = p;
			return;
		}
		p = p->next;
	}

	printf("Cannot find the node!\n");
}

void Delete(Link head, int num)
{
	Link p = head->next;

	while(p != head)
	{
		if(p->num == num)
		{
			p->prior->next = p->next;
			p->next->prior = p->prior;
			free(p);
			return;
		}
		p = p->next;
	}

	printf("Cannot find the node!\n");
}

void Display(Link head)
{
	Link p = head->next;

	if(p == head)
	{
		printf("Link is empty!\n");
		return;
	}

	while(p != head)
	{
		printf("num = %d\n", p->num);
		p = p->next;
	}
}

void MakeEmpty(Link head)
{
	Link p = head->next;

	while(p != head)
	{
		head->next = head->next->next;
		free(p);
		p = head->next;
	}

	head->prior = head;
}

void ReleaseLink(Link *head)
{
	MakeEmpty(*head);
	free(*head);
	*head = NULL;
}

int main()
{
	Link head;
	Link new_node;
	int i;

	CreateLink(&head);

	for(i = 0; i < 7; i++)
	{
		if(CreateNode(&new_node))
		{
			new_node->num = i + 1;
			InsertTail(head,new_node);
		}
	}

	Display(head);
	printf("\n");

	if(CreateNode(&new_node))
	{
		new_node->num = 23;
		InsertBefore(head,new_node,3);
	}

	Delete(head, 6);

	Display(head);
	printf("\n");

	MakeEmpty(head);

	for(i = 0; i < 7; i++)
	{
		if(CreateNode(&new_node))
		{
			new_node->num = i + 1;
			InsertTail(head,new_node);
		}
	}

	Display(head);
	printf("\n");

	ReleaseLink(&head);


	return 0;
}

 

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