1. 程式人生 > >無頭單向非迴圈連結串列基本操作實現

無頭單向非迴圈連結串列基本操作實現

之前寫了動態順序表的實現,但動態順序表還是存在以下問題

  1. 中間/頭部的插入刪除,時間複雜度為O(N)
  2. 增容需要申請新空間,拷貝資料,釋放舊空間。會有不小的消耗。
  3. 增容一般是呈2倍的增長,勢必會有一定的空間浪費。例如當前容量為100,滿了以後增容到200,
    我們再繼續插入了5個數據,後面沒有資料插入了,那麼就浪費了95個數據空間。
    所以我們有引入一種新的資料結構連結串列來解決順序表所存在的問題
    ** SList.h**
#ifndef __SLIST_H__
#define __SLIST_H__

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

typedef int SLDataType;

typedef struct SListNode
{
	SLDataType _a;
	struct SListNode* _next;
}SListNode;

typedef struct SList
{
	SListNode* _head;
}SList;

void SListInit(SList* psl);
void SListDestory(SList* psl);

void SListPushBack(SList* psl, SLDataType x);
void SListPopBack(SList* psl);
void SListPushFront(SList* psl, SLDataType x);
void SListPopFront(SList* psl);

SListNode* SListFind(SList* psl, SLDataType x);
void SListInsertAfter(SListNode* pos, SLDataType x);//在指定位置後面插入
void SListEraseAfter(SListNode* pos);
void SListRemove(SList* psl, SLDataType x);
void SListPrint(SList* psl);
void Test();
#endif //__SLIST_H__

//單鏈表的頭刪和尾刪都要對只有一個節點進行判斷。
//單鏈表的頭插入和尾插入,也要對只有一個節點進行處理;

** SList.h**

#include "SList.h"

void SListInit(SList* psl)
{
	assert(psl);
	psl->_head = NULL;
}

void SListDestory(SList* psl)
{
	SListNode* cur = psl->_head;
	SListNode* next = NULL;
	assert(psl);
	while(cur != NULL)
	{
		next = cur->_next;
		free(cur);
		cur = NULL;
		cur = next;
	}
	psl->_head = NULL;
}

SListNode* SListBuyNode(SLDataType x)
{
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	newnode->_a = x;
	newnode->_next = NULL;
	return newnode;
}

void SListPushBack(SList* psl, SLDataType x)
{
	SListNode* cur = psl->_head;
	assert(psl);
	if(psl->_head == NULL)
	{
		psl->_head = SListBuyNode(x);
	}
	else
	{
		while(cur->_next != NULL)
		{
			cur = cur->_next;
		}
		cur->_next = SListBuyNode(x);
	}
}

void SListPopBack(SList* psl)
{
	SListNode* prev = NULL;
	SListNode* cur = psl->_head;
	assert(psl);
	//對只有一個節點特殊處理
	if(cur->_next == NULL)
	{
		free(cur);
		cur = NULL;
		psl->_head = NULL;	
	}
	else
	{
		//單鏈表找尾,用指標的next判斷
		while(cur->_next != NULL)
	{
		prev = cur;
		cur = cur->_next;
	}
		free(cur);
		cur = NULL;
		prev->_next = NULL;
	}
}

void SListPushFront(SList* psl, SLDataType x)
{
	SListNode* node = NULL;
	assert(psl);
	if(psl->_head == NULL)
	{
		psl->_head = SListBuyNode(x);
	}
	else
	{
		node = SListBuyNode(x);
		node->_next = psl->_head;
		psl->_head = node;
	}
}

void SListPopFront(SList* psl)
{
	SListNode* del = psl->_head;
	assert(psl);
	if(del->_next == NULL)
	{
		free(del);
		del = NULL;
		psl->_head = NULL;
	}
	else
	{
		psl->_head = del->_next;
		free(del);
		del = NULL;
	}

}


void SListPrint(SList* psl)
{
	 SListNode* cur = psl->_head;
	 assert(psl);
	 while(cur != NULL)
	 {
		 printf("%d ", cur->_a);
		 cur = cur->_next;
	 }
	 printf("\n");
}

void SListInsertAfter(SListNode* pos, SLDataType x)
{
	SListNode* next = pos->_next;
	SListNode* node = NULL;
	assert(pos);
	node = SListBuyNode(x);
	pos->_next = node;
	node = next;
}

void SListEraseAfter(SListNode* pos)
{
	SListNode* del = pos->_next;
	SListNode* next = del->_next;
	pos->_next = next;
	free(del);
	del = NULL;
}
SListNode* SListFind(SList* psl, SLDataType x)
{
	SListNode* cur = psl->_head;
	assert(psl);
	while(cur != NULL)
	{
		if(cur->_a == x)
		{
			return cur;
		}
		else
		{
			cur = cur->_next;
		}
	}
	return NULL;
}

void SListRemove(SList* psl, SLDataType x)
{
	SListNode* prev = NULL;
	SListNode* pos = psl->_head;
	assert(psl);
	while(pos != NULL)
	{
		prev = pos;
		if(pos->_a == x)
		{
			break;
		}
		else
		{
			pos = pos->_next;
		}
	}
	if(pos == NULL)
	{
		;
	}
	else
	{
		prev->_next = pos->_next;
		free(pos);
		pos = NULL;
	}
}
void Test()
{
	SList s;
	SListInit(&s);
	SListPushBack(&s, 1);
	SListPushBack(&s, 2);
	SListPushBack(&s, 3);
	SListPushBack(&s, 4);
	SListPrint(&s);

	//SListPopBack(&s);
	//SListPopBack(&s);
	//SListPopBack(&s);
	//SListPopBack(&s);

	SListPushFront(&s, 10);
	/*SListPopBack(&s);
	SListPopFront(&s);
	SListPopFront(&s);
	SListPopFront(&s);*/

	SListPrint(&s);
}