单链表操作(创建、打印、计算长度、插入指定位置节点、排序、析构、逆序输出)

struct node
{
    int val;
    node* next;
};

//此处需要注意,如果写成void create(node* head,int n)
//这样即使创建了链表,也没有作用,因为node* head是形参
//在函数内部是对这个指针的拷贝进行操作,故不传回链表
//正确形式应该是void create(node* &head,int n)
node* create(unsigned int n)
{
    node *head = new node;
    node *p = head, *q;
    head->val = rand() % RAND_MAX;
    cout << "创建节点:" << 0 << " 值:" << head->val << endl;

    for (size_t i = 1; i < n; i++)
    {
        q = new node;
        q->val = rand() % RAND_MAX;
        cout << "创建节点:" << i << " 值:" << q->val << endl;

        p->next = q; //链表叠加
        p = p->next;
    }
    p->next = NULL; //切记尾端处理

    return head;
}

void erase(node* head)
{
    if (NULL == head) return;

    node *tmp;
    while (head)
    {
        tmp = head;
        head = head->next;
        delete tmp;
    }
}

int getnodelen(node* head)
{
    int n = 0;
    node *temp=head;
    while (temp)
    {
        n++;
        temp = temp->next;
    }
    return n;
}

//此题原本做法出现两处错误
//(1)void delnode(node* head, int num),此处head传递进入的是指针的拷贝,如果头节点被改变,就呵呵了
//(2)逻辑错误,原程序中只若是头节点相等,删除操作后就返回了,这种考虑是不完全的
void delnode(node* &head, int num)
{
    if (NULL == head) return;

    node *temp, *p = head;

    //删除从头节点连续相等数值
    while (head != NULL&&head->val == num)
    {
        temp = head;
        head = head->next;
        delete temp;
        cout << "删除头节点,数值为:" << num << endl;
    }

    if (head) p = head;
    else return;

    while (p->next)
    {
        if (p->next->val == num)
        {
            temp = p->next;
            //错误写成p = temp->next;
            p->next = temp->next;
            delete temp;
            cout << "删除节点,数值为:" << num << endl;
        }
        else
        {
            p = p->next;
        }
    }
}

//在链表中第i个位置插入节点,即在第i个节点前插入元素
bool insert_n_list(node* &head, int n, int num)
{
    if (n < 1 || head == NULL) return false;

    int i = 1;
    node *temp, *p = head;

    //插入头节点
    if (n == 1)
    {
        temp = new node;
        temp->val = num;
        temp->next = head;
        head = temp;
        return true;
    }

    while (p != NULL&&i < n - 1)
    {
        ++i;
        p = p->next;
    }

    if (i == n - 1 && p != NULL) //寻找到插入节点
    {
        temp = new node;
        temp->val = num;
        temp->next = p->next;
        p->next = temp;
        return true;
    }
    else
    {
        return false;
    }
}

void printnodelist(node* head)
{
    if (NULL == head) return;

    node *temp = head;
    while (temp)
    {
        cout << " " << temp->val << "," ;
        temp = temp->next;
    }
    cout << endl;
}

//按升序排列(仅进行值交换,不进行指针交换)
void sort_nodelist(node* head)
{
    if (head == NULL || head->next == NULL)
        return;

    node *p = head;
    bool sign = false;
    int i, j, len = getnodelen(head), temp;

    for (i = len - 1; i > 0; i--)
    {
        sign = false;
        p = head;
        for ( j = 0; j < i; j++)
        {
            if (p->val>p->next->val)
            {
                sign = true;
                temp = p->val;
                p->val = p->next->val;
                p->next->val = temp;
            }
            p = p->next;
        }

        if (!sign) 
            break; //此趟排序未发生交换
    }
}

void reverse_nodelist(node* &head)
{
    //空链表或者单节点链表不进行转置
    if (head == NULL || head->next == NULL)
        return;

    node *p1 = head, *p2 = head->next, *p3;

    while (p2)
    {
        p3 = p2->next;
        p2->next = p1;
        p1 = p2;
        p2 = p3;
    }

    //此处需注意最后一个节点是NULL,只有当P2为NULL时,转置方才完成
    //此时将NULL,即P2后面的P1提取出来作为头节点,转置完成
    head->next = NULL;
    head = p1;
}

2015年8月5号添加:

//可以调用递归做,但是如果链表较长,易导致栈溢出
void print_reverse(node* list)
{
    if (NULL == list)
        return;

    //单节点单独处理
    if (NULL == list->next)
    {
        cout << " " << list->val << endl;
        return;
    }

    node* temp;
    stack<int> print;
    while (NULL != temp)
    {
        print.push(temp->val);
        temp = temp->next;
    }

    int val;
    while (!print.empty()) //stack若为空,用empty判断返回true
    {
        val = print.top();
        cout << " " << val << ",";
        print.pop();
    }
    cout << endl;
}

 

posted @ 2015-08-04 16:38  从此寂静无声  阅读(355)  评论(0编辑  收藏  举报